Added additional es5 conformance tests, better emit for functions returning global promise, pass this to __generator

This commit is contained in:
Ron Buckton
2016-06-27 17:12:24 -07:00
parent 0c647c3d14
commit 203dab4412
112 changed files with 2341 additions and 322 deletions

View File

@@ -148,6 +148,7 @@ namespace ts {
let getGlobalESSymbolConstructorSymbol: () => Symbol;
let getGlobalPromiseConstructorSymbol: () => Symbol;
let tryGetGlobalPromiseConstructorSymbol: () => Symbol;
let globalObjectType: ObjectType;
let globalFunctionType: ObjectType;
@@ -13922,7 +13923,7 @@ namespace ts {
* @param returnType The return type of a FunctionLikeDeclaration
* @param location The node on which to report the error.
*/
function checkCorrectPromiseType(returnType: Type, location: Node) {
function checkCorrectPromiseType(returnType: Type, location: Node, diagnostic: DiagnosticMessage, typeName?: string) {
if (returnType === unknownType) {
// The return type already had some other error, so we ignore and return
// the unknown type.
@@ -13941,7 +13942,7 @@ namespace ts {
// The promise type was not a valid type reference to the global promise type, so we
// report an error and return the unknown type.
error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
error(location, diagnostic, typeName);
return unknownType;
}
@@ -13961,7 +13962,7 @@ namespace ts {
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
if (languageVersion >= ScriptTarget.ES6) {
const returnType = getTypeFromTypeNode(node.type);
return checkCorrectPromiseType(returnType, node.type);
return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
}
const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
@@ -14007,11 +14008,11 @@ namespace ts {
const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
// try to fall back to global promise type.
const typeName = promiseConstructor
? symbolToString(promiseConstructor)
: typeToString(promiseType);
error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
return unknownType;
return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
}
// If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
@@ -14019,7 +14020,7 @@ namespace ts {
// Validate the promise constructor type.
const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
return unknownType;
}
@@ -17520,6 +17521,11 @@ namespace ts {
function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
return TypeReferenceSerializationKind.Promise;
}
const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
if (constructorType && isConstructorType(constructorType)) {
return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
@@ -17538,8 +17544,8 @@ namespace ts {
else if (type.flags & TypeFlags.Any) {
return TypeReferenceSerializationKind.ObjectType;
}
else if (isTypeOfKind(type, TypeFlags.Void)) {
return TypeReferenceSerializationKind.VoidType;
else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
return TypeReferenceSerializationKind.VoidNullableOrNeverType;
}
else if (isTypeOfKind(type, TypeFlags.Boolean)) {
return TypeReferenceSerializationKind.BooleanType;
@@ -17837,6 +17843,7 @@ namespace ts {
getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
getGlobalPromiseConstructorSymbol = memoize(() => getGlobalValueSymbol("Promise"));
tryGetGlobalPromiseConstructorSymbol = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Value, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol());
getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
getGlobalThenableType = memoize(createThenableType);

View File

@@ -72,7 +72,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};`;
const generatorHelper = `
var __generator = (this && this.__generator) || function (body) {
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
@@ -97,7 +97,7 @@ var __generator = (this && this.__generator) || function (body) {
_.trys.pop();
continue;
}
op = body(_);
op = body.call(thisArg, _);
}
catch (e) { op = [6, e]; }
finally { f = 0, sent = void 0; }

View File

@@ -2554,21 +2554,24 @@ namespace ts {
return createCall(
createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
/*typeArguments*/ undefined,
[setNodeEmitFlags(
createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(state)],
/*type*/ undefined,
createBlock(
buildResult,
/*location*/ undefined,
/*multiLine*/ buildResult.length > 0
)
),
NodeEmitFlags.ReuseTempVariableScope
)]
[
createThis(),
setNodeEmitFlags(
createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(state)],
/*type*/ undefined,
createBlock(
buildResult,
/*location*/ undefined,
/*multiLine*/ buildResult.length > 0
)
),
NodeEmitFlags.ReuseTempVariableScope
)
]
);
}

View File

@@ -1774,7 +1774,7 @@ namespace ts {
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false);
case TypeReferenceSerializationKind.VoidType:
case TypeReferenceSerializationKind.VoidNullableOrNeverType:
return createVoidZero();
case TypeReferenceSerializationKind.BooleanType:
@@ -1797,6 +1797,9 @@ namespace ts {
case TypeReferenceSerializationKind.TypeWithCallSignature:
return createIdentifier("Function");
case TypeReferenceSerializationKind.Promise:
return createIdentifier("Promise");
case TypeReferenceSerializationKind.ObjectType:
default:
return createIdentifier("Object");
@@ -2221,8 +2224,21 @@ namespace ts {
}
}
function getPromiseConstructor(type: TypeNode) {
const typeName = getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
return typeName;
}
}
return undefined;
}
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getEntityNameFromTypeNode(node.type) : undefined;
const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getPromiseConstructor(node.type) : undefined;
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;

View File

@@ -2043,12 +2043,13 @@ namespace ts {
// function that can be reached at runtime (e.g. a `class`
// declaration or a `var` declaration for the static side
// of a type, such as the global `Promise` type in lib.d.ts).
VoidType, // The TypeReferenceNode resolves to a Void-like type.
VoidNullableOrNeverType, // The TypeReferenceNode resolves to a Void-like, Nullable, or Never type.
NumberLikeType, // The TypeReferenceNode resolves to a Number-like type.
StringLikeType, // The TypeReferenceNode resolves to a String-like type.
BooleanType, // The TypeReferenceNode resolves to a Boolean-like type.
ArrayLikeType, // The TypeReferenceNode resolves to an Array-like type.
ESSymbolType, // The TypeReferenceNode resolves to the ESSymbol type.
Promise, // The TypeReferenceNode resolved to the global Promise constructor symbol.
TypeWithCallSignature, // The TypeReferenceNode resolves to a Function type or a type
// with call signatures.
ObjectType, // The TypeReferenceNode resolves to any other type.