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

Allow decorators in ES3 #4741

Merged
merged 4 commits into from
Oct 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8564,6 +8564,12 @@ namespace ts {
case SyntaxKind.SetAccessor:
// A method or accessor declaration decorator will have two or three arguments (see
// `PropertyDecorator` and `MethodDecorator` in core.d.ts)

// If we are emitting decorators for ES3, we will only pass two arguments.
if (languageVersion === ScriptTarget.ES3) {
return 2;
}

// If the method decorator signature only accepts a target and a key, we will only
// type check those arguments.
return signature.parameters.length >= 3 ? 3 : 2;
Expand Down Expand Up @@ -14917,9 +14923,6 @@ namespace ts {
if (!nodeCanBeDecorated(node)) {
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
}
else if (languageVersion < ScriptTarget.ES5) {
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
}
else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, <AccessorDeclaration>node);
if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,6 @@
"category": "Error",
"code": 1204
},
"Decorators are only available when targeting ECMAScript 5 and higher.": {
"category": "Error",
"code": 1205
},
"Decorators are not valid here.": {
"category": "Error",
"code": 1206
Expand Down
69 changes: 26 additions & 43 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,10 @@ var __extends = (this && this.__extends) || function (d, b) {
// emit output for the __decorate helper function
const decorateHelper = `
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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;
};`;

// emit output for the __metadata helper function
Expand Down Expand Up @@ -1652,7 +1650,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// The emit for the decorated computed property decorator is:
//
// Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
// __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a));
//
if (nodeIsDecorated(node.parent)) {
if (!computedPropertyNamesToGeneratedNames) {
Expand Down Expand Up @@ -4707,7 +4705,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// let C = class {
// };
// Object.defineProperty(C, "name", { value: "C", configurable: true });
// C = __decorate([dec], C);
//
// * For an exported class declaration:
Expand All @@ -4719,7 +4716,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// export let C = class {
// };
// Object.defineProperty(C, "name", { value: "C", configurable: true });
// C = __decorate([dec], C);
//
// * For a default export of a class declaration with a name:
Expand All @@ -4731,7 +4727,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// let C = class {
// }
// Object.defineProperty(C, "name", { value: "C", configurable: true });
// C = __decorate([dec], C);
// export default C;
//
Expand Down Expand Up @@ -5059,21 +5054,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// The emit for a method is:
//
// Object.defineProperty(C.prototype, "method",
// __decorate([
// dec,
// __param(0, dec2),
// __metadata("design:type", Function),
// __metadata("design:paramtypes", [Object]),
// __metadata("design:returntype", void 0)
// ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
// __decorate([
// dec,
// __param(0, dec2),
// __metadata("design:type", Function),
// __metadata("design:paramtypes", [Object]),
// __metadata("design:returntype", void 0)
// ], C.prototype, "method", undefined);
//
// The emit for an accessor is:
//
// Object.defineProperty(C.prototype, "accessor",
// __decorate([
// dec
// ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
// __decorate([
// dec
// ], C.prototype, "accessor", undefined);
//
// The emit for a property is:
//
Expand All @@ -5084,18 +5077,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi

writeLine();
emitStart(member);
if (member.kind !== SyntaxKind.PropertyDeclaration) {
write("Object.defineProperty(");
emitStart(member.name);
emitClassMemberPrefix(node, member);
write(", ");
emitExpressionForPropertyName(member.name);
emitEnd(member.name);
write(",");
increaseIndent();
writeLine();
}

write("__decorate([");
increaseIndent();
writeLine();
Expand All @@ -5119,15 +5100,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitExpressionForPropertyName(member.name);
emitEnd(member.name);

if (member.kind !== SyntaxKind.PropertyDeclaration) {
write(", Object.getOwnPropertyDescriptor(");
emitStart(member.name);
emitClassMemberPrefix(node, member);
write(", ");
emitExpressionForPropertyName(member.name);
emitEnd(member.name);
write("))");
decreaseIndent();
if (languageVersion > ScriptTarget.ES3) {
if (member.kind !== SyntaxKind.PropertyDeclaration) {
// We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly.
// We have this extra argument here so that we can inject an explicit property descriptor at a later date.
write(", null");
}
else {
// We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it
// should not invoke `Object.getOwnPropertyDescriptor`.
write(", void 0");
}
}

write(");");
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ namespace ts {
sourceFile.fileWatcher.close();
sourceFile.fileWatcher = undefined;
if (removed) {
var index = rootFileNames.indexOf(sourceFile.fileName);
let index = rootFileNames.indexOf(sourceFile.fileName);
if (index >= 0) {
rootFileNames.splice(index, 1);
}
Expand Down
10 changes: 4 additions & 6 deletions tests/baselines/reference/classExpressionWithDecorator1.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ var v = @decorate class C { static p = 1 };

//// [classExpressionWithDecorator1.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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 v = ;
var C = (function () {
Expand Down
10 changes: 4 additions & 6 deletions tests/baselines/reference/decoratedClassFromExternalModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import Decorated from 'decorated';

//// [decorated.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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;
};
function decorate(target) { }
let Decorated = class {
Expand Down
25 changes: 11 additions & 14 deletions tests/baselines/reference/decoratorChecksFunctionBodies.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ class A {

//// [decoratorChecksFunctionBodies.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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;
};
// from #2971
function func(s) {
Expand All @@ -32,13 +30,12 @@ var A = (function () {
}
A.prototype.m = function () {
};
Object.defineProperty(A.prototype, "m",
__decorate([
(function (x, p) {
var a = 3;
func(a);
return x;
})
], A.prototype, "m", Object.getOwnPropertyDescriptor(A.prototype, "m")));
__decorate([
(function (x, p) {
var a = 3;
func(a);
return x;
})
], A.prototype, "m", null);
return A;
})();
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ class Wat {
exports.test = 'abc';
//// [b.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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 a_1 = require('./a');
function filter(handler) {
Expand All @@ -45,9 +43,8 @@ var Wat = (function () {
Wat.whatever = function () {
// ...
};
Object.defineProperty(Wat, "whatever",
__decorate([
filter(function () { return a_1.test == 'abc'; })
], Wat, "whatever", Object.getOwnPropertyDescriptor(Wat, "whatever")));
__decorate([
filter(function () { return a_1.test == 'abc'; })
], Wat, "whatever", null);
return Wat;
})();
10 changes: 4 additions & 6 deletions tests/baselines/reference/decoratorMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Service;
//// [component.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ var MyClass = (function () {
}
MyClass.prototype.doSomething = function () {
};
Object.defineProperty(MyClass.prototype, "doSomething",
__decorate([
decorator,
__metadata('design:type', Function),
__metadata('design:paramtypes', []),
__metadata('design:returntype', void 0)
], MyClass.prototype, "doSomething", Object.getOwnPropertyDescriptor(MyClass.prototype, "doSomething")));
__decorate([
decorator,
__metadata('design:type', Function),
__metadata('design:paramtypes', []),
__metadata('design:returntype', void 0)
], MyClass.prototype, "doSomething", null);
return MyClass;
})();
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var B = (function () {
__decorate([
decorator,
__metadata('design:type', Object)
], B.prototype, "x");
], B.prototype, "x", void 0);
return B;
})();
exports.B = B;
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var B = (function () {
__decorate([
decorator,
__metadata('design:type', A)
], B.prototype, "x");
], B.prototype, "x", void 0);
return B;
})();
exports.B = B;
10 changes: 4 additions & 6 deletions tests/baselines/reference/decoratorOnClass1.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ class C {

//// [decoratorOnClass1.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
switch (arguments.length) {
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, 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 C = (function () {
function C() {
Expand Down
Loading