Skip to content

Commit f3e03db

Browse files
author
Arthur Ozga
committed
merge with master
2 parents 24753c4 + bb3fb7d commit f3e03db

28 files changed

Lines changed: 413 additions & 112 deletions

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
"tslint": "latest"
3838
},
3939
"scripts": {
40-
"test": "jake runtests"
40+
"pretest": "jake tests",
41+
"test": "jake runtests",
42+
"build": "npm run build:compiler && npm run build:tests",
43+
"build:compiler": "jake local",
44+
"build:tests": "jake tests",
45+
"clean": "jake clean"
4146
}
4247
}

src/compiler/checker.ts

Lines changed: 77 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6436,98 +6436,108 @@ namespace ts {
64366436
let classType = classDeclaration && <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(classDeclaration));
64376437
let baseClassType = classType && getBaseTypes(classType)[0];
64386438

6439+
let container = getSuperContainer(node, /*includeFunctions*/ true);
6440+
let needToCaptureLexicalThis = false;
6441+
6442+
if (!isCallExpression) {
6443+
// adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting
6444+
while (container && container.kind === SyntaxKind.ArrowFunction) {
6445+
container = getSuperContainer(container, /*includeFunctions*/ true);
6446+
needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6;
6447+
}
6448+
}
6449+
6450+
let canUseSuperExpression = isLegalUsageOfSuperExpression(container);
6451+
let nodeCheckFlag: NodeCheckFlags = 0;
6452+
6453+
// always set NodeCheckFlags for 'super' expression node
6454+
if (canUseSuperExpression) {
6455+
if ((container.flags & NodeFlags.Static) || isCallExpression) {
6456+
nodeCheckFlag = NodeCheckFlags.SuperStatic;
6457+
}
6458+
else {
6459+
nodeCheckFlag = NodeCheckFlags.SuperInstance;
6460+
}
6461+
6462+
getNodeLinks(node).flags |= nodeCheckFlag;
6463+
6464+
if (needToCaptureLexicalThis) {
6465+
// call expressions are allowed only in constructors so they should always capture correct 'this'
6466+
// super property access expressions can also appear in arrow functions -
6467+
// in this case they should also use correct lexical this
6468+
captureLexicalThis(node.parent, container);
6469+
}
6470+
}
6471+
64396472
if (!baseClassType) {
64406473
if (!classDeclaration || !getClassExtendsHeritageClauseElement(classDeclaration)) {
64416474
error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class);
64426475
}
6476+
return unknownType;
6477+
}
6478+
6479+
if (!canUseSuperExpression) {
6480+
if (container && container.kind === SyntaxKind.ComputedPropertyName) {
6481+
error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
6482+
}
6483+
else if (isCallExpression) {
6484+
error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
6485+
}
6486+
else {
6487+
error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
6488+
}
6489+
64436490
return unknownType;
64446491
}
6492+
6493+
if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) {
6494+
// issue custom error message for super property access in constructor arguments (to be aligned with old compiler)
6495+
error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
6496+
return unknownType;
6497+
}
6498+
6499+
return nodeCheckFlag === NodeCheckFlags.SuperStatic
6500+
? getBaseConstructorTypeOfClass(classType)
6501+
: baseClassType;
6502+
6503+
function isLegalUsageOfSuperExpression(container: Node): boolean {
6504+
if (!container) {
6505+
return false;
6506+
}
64456507

6446-
let container = getSuperContainer(node, /*includeFunctions*/ true);
6447-
6448-
if (container) {
6449-
let canUseSuperExpression = false;
6450-
let needToCaptureLexicalThis: boolean;
64516508
if (isCallExpression) {
64526509
// TS 1.0 SPEC (April 2014): 4.8.1
64536510
// Super calls are only permitted in constructors of derived classes
6454-
canUseSuperExpression = container.kind === SyntaxKind.Constructor;
6511+
return container.kind === SyntaxKind.Constructor;
64556512
}
64566513
else {
64576514
// TS 1.0 SPEC (April 2014)
64586515
// 'super' property access is allowed
64596516
// - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance
64606517
// - In a static member function or static member accessor
64616518

6462-
// super property access might appear in arrow functions with arbitrary deep nesting
6463-
needToCaptureLexicalThis = false;
6464-
while (container && container.kind === SyntaxKind.ArrowFunction) {
6465-
container = getSuperContainer(container, /*includeFunctions*/ true);
6466-
needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6;
6467-
}
6468-
64696519
// topmost container must be something that is directly nested in the class declaration
64706520
if (container && isClassLike(container.parent)) {
64716521
if (container.flags & NodeFlags.Static) {
6472-
canUseSuperExpression =
6473-
container.kind === SyntaxKind.MethodDeclaration ||
6474-
container.kind === SyntaxKind.MethodSignature ||
6475-
container.kind === SyntaxKind.GetAccessor ||
6476-
container.kind === SyntaxKind.SetAccessor;
6522+
return container.kind === SyntaxKind.MethodDeclaration ||
6523+
container.kind === SyntaxKind.MethodSignature ||
6524+
container.kind === SyntaxKind.GetAccessor ||
6525+
container.kind === SyntaxKind.SetAccessor;
64776526
}
64786527
else {
6479-
canUseSuperExpression =
6480-
container.kind === SyntaxKind.MethodDeclaration ||
6481-
container.kind === SyntaxKind.MethodSignature ||
6482-
container.kind === SyntaxKind.GetAccessor ||
6483-
container.kind === SyntaxKind.SetAccessor ||
6484-
container.kind === SyntaxKind.PropertyDeclaration ||
6485-
container.kind === SyntaxKind.PropertySignature ||
6486-
container.kind === SyntaxKind.Constructor;
6528+
return container.kind === SyntaxKind.MethodDeclaration ||
6529+
container.kind === SyntaxKind.MethodSignature ||
6530+
container.kind === SyntaxKind.GetAccessor ||
6531+
container.kind === SyntaxKind.SetAccessor ||
6532+
container.kind === SyntaxKind.PropertyDeclaration ||
6533+
container.kind === SyntaxKind.PropertySignature ||
6534+
container.kind === SyntaxKind.Constructor;
64876535
}
64886536
}
64896537
}
6490-
6491-
if (canUseSuperExpression) {
6492-
let returnType: Type;
6493-
6494-
if ((container.flags & NodeFlags.Static) || isCallExpression) {
6495-
getNodeLinks(node).flags |= NodeCheckFlags.SuperStatic;
6496-
returnType = getBaseConstructorTypeOfClass(classType);
6497-
}
6498-
else {
6499-
getNodeLinks(node).flags |= NodeCheckFlags.SuperInstance;
6500-
returnType = baseClassType;
6501-
}
6502-
6503-
if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) {
6504-
// issue custom error message for super property access in constructor arguments (to be aligned with old compiler)
6505-
error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
6506-
returnType = unknownType;
6507-
}
6508-
6509-
if (!isCallExpression && needToCaptureLexicalThis) {
6510-
// call expressions are allowed only in constructors so they should always capture correct 'this'
6511-
// super property access expressions can also appear in arrow functions -
6512-
// in this case they should also use correct lexical this
6513-
captureLexicalThis(node.parent, container);
6514-
}
6515-
6516-
return returnType;
6517-
}
6518-
}
6519-
6520-
if (container && container.kind === SyntaxKind.ComputedPropertyName) {
6521-
error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
6522-
}
6523-
else if (isCallExpression) {
6524-
error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
6525-
}
6526-
else {
6527-
error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
6528-
}
6529-
6530-
return unknownType;
6538+
6539+
return false;
6540+
}
65316541
}
65326542

65336543
// Return contextual type of parameter or undefined if no contextual type is available

src/compiler/emitter.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6259,6 +6259,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
62596259
write(`], function(${exportFunctionForFile}) {`);
62606260
writeLine();
62616261
increaseIndent();
6262+
emitEmitHelpers(node);
62626263
emitCaptureThisForNodeIfNecessary(node);
62636264
emitSystemModuleBody(node, startIndex);
62646265
decreaseIndent();
@@ -6330,6 +6331,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
63306331
}
63316332

63326333
function emitAMDModule(node: SourceFile, startIndex: number) {
6334+
emitEmitHelpers(node);
63336335
collectExternalModuleInfo(node);
63346336

63356337
writeLine();
@@ -6351,6 +6353,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
63516353
}
63526354

63536355
function emitCommonJSModule(node: SourceFile, startIndex: number) {
6356+
emitEmitHelpers(node);
63546357
collectExternalModuleInfo(node);
63556358
emitExportStarHelper();
63566359
emitCaptureThisForNodeIfNecessary(node);
@@ -6360,6 +6363,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
63606363
}
63616364

63626365
function emitUMDModule(node: SourceFile, startIndex: number) {
6366+
emitEmitHelpers(node);
63636367
collectExternalModuleInfo(node);
63646368

63656369
// Module is detected first to support Browserify users that load into a browser with an AMD loader
@@ -6389,6 +6393,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
63896393
exportSpecifiers = undefined;
63906394
exportEquals = undefined;
63916395
hasExportStars = false;
6396+
emitEmitHelpers(node);
63926397
emitCaptureThisForNodeIfNecessary(node);
63936398
emitLinesStartingAt(node.statements, startIndex);
63946399
emitTempDeclarations(/*newLine*/ true);
@@ -6527,14 +6532,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
65276532
}
65286533
}
65296534

6530-
function emitSourceFileNode(node: SourceFile) {
6531-
// Start new file on new line
6532-
writeLine();
6533-
emitDetachedComments(node);
6534-
6535-
// emit prologue directives prior to __extends
6536-
let startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
6537-
6535+
function emitEmitHelpers(node: SourceFile): void {
65386536
// Only emit helpers if the user did not say otherwise.
65396537
if (!compilerOptions.noEmitHelpers) {
65406538
// Only Emit __extends function when target ES5.
@@ -6562,6 +6560,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
65626560
awaiterEmitted = true;
65636561
}
65646562
}
6563+
}
6564+
6565+
function emitSourceFileNode(node: SourceFile) {
6566+
// Start new file on new line
6567+
writeLine();
6568+
emitShebang();
6569+
emitDetachedComments(node);
6570+
6571+
// emit prologue directives prior to __extends
6572+
let startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
65656573

65666574
if (isExternalModule(node) || compilerOptions.isolatedModules) {
65676575
if (languageVersion >= ScriptTarget.ES6) {
@@ -6585,6 +6593,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
65856593
exportSpecifiers = undefined;
65866594
exportEquals = undefined;
65876595
hasExportStars = false;
6596+
emitEmitHelpers(node);
65886597
emitCaptureThisForNodeIfNecessary(node);
65896598
emitLinesStartingAt(node.statements, startIndex);
65906599
emitTempDeclarations(/*newLine*/ true);
@@ -6978,6 +6987,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
69786987
}
69796988
}
69806989
}
6990+
6991+
function emitShebang() {
6992+
let shebang = getShebang(currentSourceFile.text);
6993+
if (shebang) {
6994+
write(shebang);
6995+
}
6996+
}
69816997

69826998
function isPinnedOrTripleSlashComment(comment: CommentRange) {
69836999
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {

src/compiler/scanner.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ namespace ts {
408408
case CharacterCodes.greaterThan:
409409
// Starts of conflict marker trivia
410410
return true;
411+
case CharacterCodes.hash:
412+
// Only if its the beginning can we have #! trivia
413+
return pos === 0;
411414
default:
412415
return ch > CharacterCodes.maxAsciiCharacter;
413416
}
@@ -468,6 +471,13 @@ namespace ts {
468471
}
469472
break;
470473

474+
case CharacterCodes.hash:
475+
if (isShebangTrivia(text, pos)) {
476+
pos = scanShebangTrivia(text, pos);
477+
continue;
478+
}
479+
break;
480+
471481
default:
472482
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
473483
pos++;
@@ -535,6 +545,20 @@ namespace ts {
535545
return pos;
536546
}
537547

548+
const shebangTriviaRegex = /^#!.*/;
549+
550+
function isShebangTrivia(text: string, pos: number) {
551+
// Shebangs check must only be done at the start of the file
552+
Debug.assert(pos === 0);
553+
return shebangTriviaRegex.test(text);
554+
}
555+
556+
function scanShebangTrivia(text: string, pos: number) {
557+
let shebang = shebangTriviaRegex.exec(text)[0];
558+
pos = pos + shebang.length;
559+
return pos;
560+
}
561+
538562
/**
539563
* Extract comments from text prefixing the token closest following `pos`.
540564
* The return value is an array containing a TextRange for each comment.
@@ -628,6 +652,13 @@ namespace ts {
628652
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
629653
return getCommentRanges(text, pos, /*trailing*/ true);
630654
}
655+
656+
/** Optionally, get the shebang */
657+
export function getShebang(text: string): string {
658+
return shebangTriviaRegex.test(text)
659+
? shebangTriviaRegex.exec(text)[0]
660+
: undefined;
661+
}
631662

632663
export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean {
633664
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
@@ -1098,6 +1129,18 @@ namespace ts {
10981129
return token = SyntaxKind.EndOfFileToken;
10991130
}
11001131
let ch = text.charCodeAt(pos);
1132+
1133+
// Special handling for shebang
1134+
if (ch === CharacterCodes.hash && pos === 0 && isShebangTrivia(text, pos)) {
1135+
pos = scanShebangTrivia(text ,pos);
1136+
if (skipTrivia) {
1137+
continue;
1138+
}
1139+
else {
1140+
return token = SyntaxKind.ShebangTrivia;
1141+
}
1142+
}
1143+
11011144
switch (ch) {
11021145
case CharacterCodes.lineFeed:
11031146
case CharacterCodes.carriageReturn:

0 commit comments

Comments
 (0)