Merge branch 'master' into typeParametersAsConstraints

Conflicts:
	tests/baselines/reference/functionConstraintSatisfaction2.errors.txt
This commit is contained in:
Anders Hejlsberg
2015-12-05 10:42:25 -08:00
1512 changed files with 39749 additions and 17432 deletions
+315 -153
View File
@@ -51,6 +51,7 @@ namespace ts {
const emitResolver = createResolver();
const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
undefinedSymbol.declarations = [];
const argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
const checker: TypeChecker = {
@@ -141,9 +142,6 @@ namespace ts {
let globalRegExpType: ObjectType;
let globalTemplateStringsArrayType: ObjectType;
let globalESSymbolType: ObjectType;
let jsxElementType: ObjectType;
/** Lazily loaded, use getJsxIntrinsicElementType() */
let jsxIntrinsicElementsType: ObjectType;
let globalIterableType: GenericType;
let globalIteratorType: GenericType;
let globalIterableIteratorType: GenericType;
@@ -208,12 +206,17 @@ namespace ts {
}
};
let jsxElementType: ObjectType;
/** Things we lazy load from the JSX namespace */
const jsxTypes: Map<ObjectType> = {};
const JsxNames = {
JSX: "JSX",
IntrinsicElements: "IntrinsicElements",
ElementClass: "ElementClass",
ElementAttributesPropertyNameContainer: "ElementAttributesProperty",
Element: "Element"
Element: "Element",
IntrinsicAttributes: "IntrinsicAttributes",
IntrinsicClassAttributes: "IntrinsicClassAttributes"
};
const subtypeRelation: Map<RelationComparisonResult> = {};
@@ -232,6 +235,10 @@ namespace ts {
ResolvedReturnType
}
const builtinGlobals: SymbolTable = {
[undefinedSymbol.name]: undefinedSymbol
};
initializeTypeChecker();
return checker;
@@ -358,6 +365,24 @@ namespace ts {
}
}
function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) {
for (const id in source) {
if (hasProperty(source, id)) {
if (hasProperty(target, id)) {
// Error on redeclarations
forEach(target[id].declarations, addDeclarationDiagnostic(id, message));
}
else {
target[id] = source[id];
}
}
}
function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) {
return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id));
}
}
function getSymbolLinks(symbol: Symbol): SymbolLinks {
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
const id = getSymbolId(symbol);
@@ -377,6 +402,14 @@ namespace ts {
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
}
/** Is this type one of the apparent types created from the primitive types. */
function isPrimitiveApparentType(type: Type): boolean {
return type === globalStringType ||
type === globalNumberType ||
type === globalBooleanType ||
type === globalESSymbolType;
}
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
if (meaning && hasProperty(symbols, name)) {
const symbol = symbols[name];
@@ -1093,39 +1126,81 @@ namespace ts {
return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
}
function extendExportSymbols(target: SymbolTable, source: SymbolTable) {
interface ExportCollisionTracker {
specifierText: string;
exportsWithDuplicate: ExportDeclaration[];
}
/**
* Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
* Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
*/
function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: Map<ExportCollisionTracker>, exportNode?: ExportDeclaration) {
for (const id in source) {
if (id !== "default" && !hasProperty(target, id)) {
target[id] = source[id];
if (lookupTable && exportNode) {
lookupTable[id] = {
specifierText: getTextOfNode(exportNode.moduleSpecifier)
} as ExportCollisionTracker;
}
}
else if (lookupTable && exportNode && id !== "default" && hasProperty(target, id) && resolveSymbol(target[id]) !== resolveSymbol(source[id])) {
if (!lookupTable[id].exportsWithDuplicate) {
lookupTable[id].exportsWithDuplicate = [exportNode];
}
else {
lookupTable[id].exportsWithDuplicate.push(exportNode);
}
}
}
}
function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
let result: SymbolTable;
const visitedSymbols: Symbol[] = [];
visit(moduleSymbol);
return result || moduleSymbol.exports;
return visit(moduleSymbol) || moduleSymbol.exports;
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
function visit(symbol: Symbol) {
if (symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol)) {
visitedSymbols.push(symbol);
if (symbol !== moduleSymbol) {
if (!result) {
result = cloneSymbolTable(moduleSymbol.exports);
}
extendExportSymbols(result, symbol.exports);
}
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
for (const node of exportStars.declarations) {
visit(resolveExternalModuleName(node, (<ExportDeclaration>node).moduleSpecifier));
}
}
function visit(symbol: Symbol): SymbolTable {
if (!(symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol))) {
return;
}
visitedSymbols.push(symbol);
const symbols = cloneSymbolTable(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
const nestedSymbols: SymbolTable = {};
const lookupTable: Map<ExportCollisionTracker> = {};
for (const node of exportStars.declarations) {
const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier);
const exportedSymbols = visit(resolvedModule);
extendExportSymbols(
nestedSymbols,
exportedSymbols,
lookupTable,
node as ExportDeclaration
);
}
for (const id in lookupTable) {
const { exportsWithDuplicate } = lookupTable[id];
// It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself
if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || hasProperty(symbols, id)) {
continue;
}
for (const node of exportsWithDuplicate) {
diagnostics.add(createDiagnosticForNode(
node,
Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity,
lookupTable[id].specifierText,
id
));
}
}
extendExportSymbols(symbols, nestedSymbols);
}
return symbols;
}
}
@@ -1519,9 +1594,9 @@ namespace ts {
return result;
}
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string {
const writer = getSingleLineStringWriter();
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, kind);
const result = writer.string();
releaseStringWriter(writer);
@@ -1873,7 +1948,7 @@ namespace ts {
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
}
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
@@ -1885,7 +1960,7 @@ namespace ts {
}
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
@@ -1899,15 +1974,12 @@ namespace ts {
writer.writeLine();
writer.increaseIndent();
for (const signature of resolved.callSignatures) {
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
for (const signature of resolved.constructSignatures) {
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
@@ -1948,7 +2020,7 @@ namespace ts {
if (p.flags & SymbolFlags.Optional) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
@@ -2068,7 +2140,12 @@ namespace ts {
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, symbolStack?: Symbol[]) {
if (kind === SignatureKind.Construct) {
writeKeyword(writer, SyntaxKind.NewKeyword);
writeSpace(writer);
}
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
// Instantiated signature, write type arguments instead
// This is achieved by passing in the mapper separately
@@ -2936,10 +3013,6 @@ namespace ts {
return type.resolvedBaseConstructorType;
}
function hasClassBaseType(type: InterfaceType): boolean {
return !!forEach(getBaseTypes(type), t => !!(t.symbol.flags & SymbolFlags.Class));
}
function getBaseTypes(type: InterfaceType): ObjectType[] {
const isClass = type.symbol.flags & SymbolFlags.Class;
const isInterface = type.symbol.flags & SymbolFlags.Interface;
@@ -3373,11 +3446,11 @@ namespace ts {
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
if (!hasClassBaseType(classType)) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
@@ -3595,7 +3668,7 @@ namespace ts {
return <ResolvedType>type;
}
// Return properties of an object type or an empty array for other types
/** Return properties of an object type or an empty array for other types */
function getPropertiesOfObjectType(type: Type): Symbol[] {
if (type.flags & TypeFlags.ObjectType) {
return resolveStructuredTypeMembers(<ObjectType>type).properties;
@@ -3603,8 +3676,8 @@ namespace ts {
return emptyArray;
}
// If the given type is an object type and that type has a property by the given name,
// return the symbol for that property.Otherwise return undefined.
/** If the given type is an object type and that type has a property by the given name,
* return the symbol for that property. Otherwise return undefined. */
function getPropertyOfObjectType(type: Type, name: string): Symbol {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -5395,20 +5468,26 @@ namespace ts {
outer: for (const t of targetSignatures) {
if (!t.hasStringLiterals || target.flags & TypeFlags.FromSignature) {
let localErrors = reportErrors;
const checkedAbstractAssignability = false;
// Only elaborate errors from the first failure
let shouldElaborateErrors = reportErrors;
for (const s of sourceSignatures) {
if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
const related = signatureRelatedTo(s, t, localErrors);
const related = signatureRelatedTo(s, t, shouldElaborateErrors);
if (related) {
result &= related;
errorInfo = saveErrorInfo;
continue outer;
}
// Only report errors from the first failure
localErrors = false;
shouldElaborateErrors = false;
}
}
// don't elaborate the primitive apparent types (like Number)
// because the actual primitives will have already been reported.
if (shouldElaborateErrors && !isPrimitiveApparentType(source)) {
reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
typeToString(source),
signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind));
}
return Ternary.False;
}
}
@@ -6038,14 +6117,25 @@ namespace ts {
function inferFromTypes(source: Type, target: Type) {
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
// Source and target are both unions or both intersections. To improve the quality of
// inferences we first reduce the types by removing constituents that are identically
// matched by a constituent in the other type. For example, when inferring from
// 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
source = reducedSource;
target = reducedTarget;
// Source and target are both unions or both intersections. First, find each
// target constituent type that has an identically matching source constituent
// type, and for each such target constituent type infer from the type to itself.
// When inferring from a type to itself we effectively find all type parameter
// occurrences within that type and infer themselves as their type arguments.
let matchingTypes: Type[];
for (const t of (<UnionOrIntersectionType>target).types) {
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>source).types)) {
(matchingTypes || (matchingTypes = [])).push(t);
inferFromTypes(t, t);
}
}
// Next, to improve the quality of inferences, reduce the source and target types by
// removing the identically matched constituents. For example, when inferring from
// 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'.
if (matchingTypes) {
source = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>source, matchingTypes);
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
}
}
if (target.flags & TypeFlags.TypeParameter) {
// If target is a type parameter, make an inference, unless the source type contains
@@ -6129,9 +6219,12 @@ namespace ts {
}
else {
source = getApparentType(source);
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (source.flags & TypeFlags.ObjectType && (
target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
target.flags & TypeFlags.Tuple ||
target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference with type arguments, a tuple type,
// the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
@@ -6204,9 +6297,9 @@ namespace ts {
}
}
function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
for (const t of target.types) {
if (isTypeIdenticalTo(source, t)) {
function typeIdenticalToSomeType(type: Type, types: Type[]): boolean {
for (const t of types) {
if (isTypeIdenticalTo(t, type)) {
return true;
}
}
@@ -6214,29 +6307,17 @@ namespace ts {
}
/**
* Return the reduced form of the source type. This type is computed by by removing all source
* constituents that have an identical match in the target type.
* Return a new union or intersection type computed by removing a given set of types
* from a given union or intersection type.
*/
function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
let sourceTypes = source.types;
let sourceIndex = 0;
let modified = false;
while (sourceIndex < sourceTypes.length) {
if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
if (!modified) {
sourceTypes = sourceTypes.slice(0);
modified = true;
}
sourceTypes.splice(sourceIndex, 1);
}
else {
sourceIndex++;
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
const reducedTypes: Type[] = [];
for (const t of type.types) {
if (!typeIdenticalToSomeType(t, typesToRemove)) {
reducedTypes.push(t);
}
}
if (modified) {
return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
}
return source;
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes, /*noSubtypeReduction*/ true) : getIntersectionType(reducedTypes);
}
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
@@ -7820,12 +7901,11 @@ namespace ts {
return type;
}
/// Returns the type JSX.IntrinsicElements. May return `unknownType` if that type is not present.
function getJsxIntrinsicElementsType() {
if (!jsxIntrinsicElementsType) {
jsxIntrinsicElementsType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.IntrinsicElements) || unknownType;
function getJsxType(name: string) {
if (jsxTypes[name] === undefined) {
return jsxTypes[name] = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType;
}
return jsxIntrinsicElementsType;
return jsxTypes[name];
}
/// Given a JSX opening element or self-closing element, return the symbol of the property that the tag name points to if
@@ -7848,7 +7928,7 @@ namespace ts {
return links.resolvedSymbol;
function lookupIntrinsicTag(node: JsxOpeningLikeElement | JsxClosingElement): Symbol {
const intrinsicElementsType = getJsxIntrinsicElementsType();
const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements);
if (intrinsicElementsType !== unknownType) {
// Property case
const intrinsicProp = getPropertyOfType(intrinsicElementsType, (<Identifier>node.tagName).text);
@@ -7880,7 +7960,7 @@ namespace ts {
// Look up the value in the current scope
if (valueSymbol && valueSymbol !== unknownSymbol) {
links.jsxFlags |= JsxFlags.ClassElement;
links.jsxFlags |= JsxFlags.ValueElement;
if (valueSymbol.flags & SymbolFlags.Alias) {
markAliasSymbolAsReferenced(valueSymbol);
}
@@ -7909,7 +7989,7 @@ namespace ts {
function getJsxElementInstanceType(node: JsxOpeningLikeElement) {
// There is no such thing as an instance type for a non-class element. This
// line shouldn't be hit.
Debug.assert(!!(getNodeLinks(node).jsxFlags & JsxFlags.ClassElement), "Should not call getJsxElementInstanceType on non-class Element");
Debug.assert(!!(getNodeLinks(node).jsxFlags & JsxFlags.ValueElement), "Should not call getJsxElementInstanceType on non-class Element");
const classSymbol = getJsxElementTagSymbol(node);
if (classSymbol === unknownSymbol) {
@@ -7936,15 +8016,7 @@ namespace ts {
}
}
const returnType = getUnionType(signatures.map(getReturnTypeOfSignature));
// Issue an error if this return type isn't assignable to JSX.ElementClass
const elemClassType = getJsxGlobalElementClassType();
if (elemClassType) {
checkTypeRelatedTo(returnType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
}
return returnType;
return getUnionType(signatures.map(getReturnTypeOfSignature));
}
/// e.g. "props" for React.d.ts,
@@ -7993,9 +8065,31 @@ namespace ts {
if (!links.resolvedJsxType) {
const sym = getJsxElementTagSymbol(node);
if (links.jsxFlags & JsxFlags.ClassElement) {
if (links.jsxFlags & JsxFlags.ValueElement) {
// Get the element instance type (the result of newing or invoking this tag)
const elemInstanceType = getJsxElementInstanceType(node);
// Is this is a stateless function component? See if its single signature is
// assignable to the JSX Element Type
const callSignature = getSingleCallSignature(getTypeOfSymbol(sym));
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType) && (paramType.flags & TypeFlags.ObjectType)) {
// Intersect in JSX.IntrinsicAttributes if it exists
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttributes !== unknownType) {
paramType = intersectTypes(intrinsicAttributes, paramType);
}
return paramType;
}
// Issue an error if this return type isn't assignable to JSX.ElementClass
const elemClassType = getJsxGlobalElementClassType();
if (elemClassType) {
checkTypeRelatedTo(elemInstanceType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
}
if (isTypeAny(elemInstanceType)) {
return links.resolvedJsxType = elemInstanceType;
}
@@ -8017,14 +8111,36 @@ namespace ts {
return links.resolvedJsxType = emptyObjectType;
}
else if (isTypeAny(attributesType) || (attributesType === unknownType)) {
// Props is of type 'any' or unknown
return links.resolvedJsxType = attributesType;
}
else if (!(attributesType.flags & TypeFlags.ObjectType)) {
// Props is not an object type
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType));
return links.resolvedJsxType = anyType;
}
else {
return links.resolvedJsxType = attributesType;
// Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
let apparentAttributesType = attributesType;
const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes);
if (intrinsicClassAttribs !== unknownType) {
const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
if (typeParams) {
if (typeParams.length === 1) {
apparentAttributesType = intersectTypes(createTypeReference(<GenericType>intrinsicClassAttribs, [elemInstanceType]), apparentAttributesType);
}
}
else {
apparentAttributesType = intersectTypes(attributesType, intrinsicClassAttribs);
}
}
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttribs !== unknownType) {
apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
}
return links.resolvedJsxType = apparentAttributesType;
}
}
}
@@ -8063,7 +8179,7 @@ namespace ts {
/// Returns all the properties of the Jsx.IntrinsicElements interface
function getJsxIntrinsicTagNames(): Symbol[] {
const intrinsics = getJsxIntrinsicElementsType();
const intrinsics = getJsxType(JsxNames.IntrinsicElements);
return intrinsics ? getPropertiesOfType(intrinsics) : emptyArray;
}
@@ -9810,7 +9926,7 @@ namespace ts {
return aggregatedTypes;
}
/*
/*
*TypeScript Specification 1.0 (6.3) - July 2014
* An explicitly typed function whose return type isn't the Void or the Any type
* must have at least one return statement somewhere in its body.
@@ -9823,31 +9939,39 @@ namespace ts {
}
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
return;
}
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
if (!returnType && !compilerOptions.noImplicitReturns) {
if (returnType === voidType || isTypeAny(returnType)) {
return;
}
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
// also if HasImplicitReturnValue flags is not set this means that all codepaths in function body end with return of throw
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
return;
}
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
if (compilerOptions.noImplicitReturns) {
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
}
}
else {
// This function does not conform to the specification.
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
if (returnType && !hasExplicitReturn) {
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
// this function does not conform to the specification.
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
}
else if (compilerOptions.noImplicitReturns) {
if (!returnType) {
// If return type annotation is omitted check if function has any explicit return statements.
// If it does not have any - its inferred return type is void - don't do any checks.
// Otherwise get inferred return type from function body and report error only if it is not void / anytype
const inferredReturnType = hasExplicitReturn
? getReturnTypeOfSignature(getSignatureFromDeclaration(func))
: voidType;
if (inferredReturnType === voidType || isTypeAny(inferredReturnType)) {
return;
}
}
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
}
}
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
@@ -11400,7 +11524,9 @@ namespace ts {
seen = c === node;
}
});
if (subsequentNode) {
// We may be here because of some extra junk between overloads that could not be parsed into a valid node.
// In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here.
if (subsequentNode && subsequentNode.pos === node.end) {
if (subsequentNode.kind === node.kind) {
const errorNode: Node = (<FunctionLikeDeclaration>subsequentNode).name || subsequentNode;
// TODO(jfreeman): These are methods, so handle computed name case
@@ -11873,6 +11999,9 @@ namespace ts {
return unknownType;
}
// If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
checkReturnTypeAnnotationAsExpression(node);
// 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)) {
@@ -11881,11 +12010,11 @@ namespace ts {
// Verify there is no local declaration that could collide with the promise constructor.
const promiseName = getEntityNameFromTypeNode(node.type);
const root = getFirstIdentifier(promiseName);
const rootSymbol = getSymbol(node.locals, root.text, SymbolFlags.Value);
const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
if (rootSymbol) {
error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
root.text,
promiseNameOrNamespaceRoot.text,
getFullyQualifiedName(promiseConstructor));
return unknownType;
}
@@ -11969,24 +12098,12 @@ namespace ts {
* Checks the type annotation of an accessor declaration or property declaration as
* an expression if it is a type reference to a type with a value declaration.
*/
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
switch (node.kind) {
case SyntaxKind.PropertyDeclaration:
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
break;
case SyntaxKind.Parameter:
checkTypeNodeAsExpression((<ParameterDeclaration>node).type);
break;
case SyntaxKind.MethodDeclaration:
checkTypeNodeAsExpression((<MethodDeclaration>node).type);
break;
case SyntaxKind.GetAccessor:
checkTypeNodeAsExpression((<AccessorDeclaration>node).type);
break;
case SyntaxKind.SetAccessor:
checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
break;
}
function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) {
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
}
function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) {
checkTypeNodeAsExpression(node.type);
}
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
@@ -12024,11 +12141,12 @@ namespace ts {
break;
case SyntaxKind.MethodDeclaration:
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
// fall-through
case SyntaxKind.SetAccessor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
checkReturnTypeAnnotationAsExpression(<FunctionLikeDeclaration>node);
break;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.Parameter:
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
@@ -12078,8 +12196,8 @@ namespace ts {
const symbol = getSymbolOfNode(node);
const localSymbol = node.localSymbol || symbol;
// Since the javascript won't do semantic analysis like typescript,
// if the javascript file comes before the typescript file and both contain same name functions,
// Since the javascript won't do semantic analysis like typescript,
// if the javascript file comes before the typescript file and both contain same name functions,
// checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function.
const firstDeclaration = forEach(localSymbol.declarations,
// Get first non javascript function declaration
@@ -14056,8 +14174,29 @@ namespace ts {
const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
}
// Checks for export * conflicts
const exports = getExportsOfModule(moduleSymbol);
for (const id in exports) {
if (id === "__export") {
continue;
}
const { declarations, flags } = exports[id];
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. (TS Exceptions: namespaces, function overloads, enums, and interfaces)
if (!(flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) && declarations.length > 1) {
const exportedDeclarations: Declaration[] = filter(declarations, isNotOverload);
if (exportedDeclarations.length > 1) {
for (const declaration of exportedDeclarations) {
diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, id));
}
}
}
}
links.exportsChecked = true;
}
function isNotOverload(declaration: Declaration): boolean {
return declaration.kind !== SyntaxKind.FunctionDeclaration || !!(declaration as FunctionDeclaration).body;
}
}
function checkTypePredicate(node: TypePredicateNode) {
@@ -14329,6 +14468,7 @@ namespace ts {
emitExtends = false;
emitDecorate = false;
emitParam = false;
emitAwaiter = false;
potentialThisCollisions.length = 0;
forEach(node.statements, checkSourceElement);
@@ -15191,10 +15331,12 @@ namespace ts {
}
});
// Setup global builtins
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
getSymbolLinks(undefinedSymbol).type = undefinedType;
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
getSymbolLinks(unknownSymbol).type = unknownType;
globals[undefinedSymbol.name] = undefinedSymbol;
// Initialize special types
globalArrayType = <GenericType>getGlobalType("Array", /*arity*/ 1);
@@ -15888,13 +16030,27 @@ namespace ts {
if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
const variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
if (!checkGrammarVariableDeclarationList(variableList)) {
if (variableList.declarations.length > 1) {
const declarations = variableList.declarations;
// declarations.length can be zero if there is an error in variable declaration in for-of or for-in
// See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details
// For example:
// var let = 10;
// for (let of [1,2,3]) {} // this is invalid ES6 syntax
// for (let in [1,2,3]) {} // this is invalid ES6 syntax
// We will then want to skip on grammar checking on variableList declaration
if (!declarations.length) {
return false;
}
if (declarations.length > 1) {
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
: Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
}
const firstDeclaration = variableList.declarations[0];
const firstDeclaration = declarations[0];
if (firstDeclaration.initializer) {
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
@@ -16093,7 +16249,7 @@ namespace ts {
}
}
const checkLetConstNames = languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node));
const checkLetConstNames = (isLet(node) || isConst(node));
// 1. LexicalDeclaration : LetOrConst BindingList ;
// It is a Syntax Error if the BoundNames of BindingList contains "let".
@@ -16107,7 +16263,7 @@ namespace ts {
function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
if (name.kind === SyntaxKind.Identifier) {
if ((<Identifier>name).text === "let") {
if ((<Identifier>name).originalKeywordKind === SyntaxKind.LetKeyword) {
return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
}
}
@@ -16235,11 +16391,17 @@ namespace ts {
if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
return true;
}
if (node.initializer) {
return grammarErrorOnNode(node.initializer, Diagnostics.An_interface_property_cannot_have_an_initializer);
}
}
else if (node.parent.kind === SyntaxKind.TypeLiteral) {
if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
return true;
}
if (node.initializer) {
return grammarErrorOnNode(node.initializer, Diagnostics.A_type_literal_property_cannot_have_an_initializer);
}
}
if (isInAmbientContext(node) && node.initializer) {
+27
View File
@@ -356,6 +356,33 @@ namespace ts {
return result;
}
/**
* Reduce the properties of a map.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
if (map) {
for (const key in map) {
if (hasProperty(map, key)) {
result = callback(result, map[key], String(key));
}
}
}
return result;
}
/**
* Tests whether a value is an array.
*/
export function isArray(value: any): value is any[] {
return Array.isArray ? Array.isArray(value) : value instanceof Array;
}
export function memoize<T>(callback: () => T): () => T {
let value: T;
return () => {
+1 -1
View File
@@ -1675,7 +1675,7 @@ namespace ts {
/* @internal */
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath);
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
if (!emitSkipped) {
const declarationOutput = emitDeclarationResult.referencePathsOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
+25 -1
View File
@@ -783,6 +783,14 @@
"category": "Error",
"code": 1245
},
"An interface property cannot have an initializer.": {
"category": "Error",
"code": 1246
},
"A type literal property cannot have an initializer.": {
"category": "Error",
"code": 1247
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
@@ -836,6 +844,10 @@
"category": "Error",
"code": 2307
},
"Module {0} has already exported a member named '{1}'. Consider explicitly re-exporting to resolve the ambiguity.": {
"category": "Error",
"code": 2308
},
"An export assignment cannot be used in a module with other exported elements.": {
"category": "Error",
"code": 2309
@@ -892,6 +904,10 @@
"category": "Error",
"code": 2322
},
"Cannot redeclare exported variable '{0}'.": {
"category": "Error",
"code": 2323
},
"Property '{0}' is missing in type '{1}'.": {
"category": "Error",
"code": 2324
@@ -1172,6 +1188,10 @@
"category": "Error",
"code": 2396
},
"Declaration name conflicts with built-in global identifier '{0}'.": {
"category": "Error",
"code": 2397
},
"Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": {
"category": "Error",
"code": 2399
@@ -1724,6 +1744,10 @@
"category": "Error",
"code": 2657
},
"Type '{0}' provides no match for the signature '{1}'": {
"category": "Error",
"code": 2658
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2430,7 +2454,7 @@
"Not all code paths return a value.": {
"category": "Error",
"code": 7030
},
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+139 -529
View File
File diff suppressed because it is too large Load Diff
+24 -13
View File
@@ -2259,6 +2259,14 @@ namespace ts {
property.name = name;
property.questionToken = questionToken;
property.type = parseTypeAnnotation();
if (token === SyntaxKind.EqualsToken) {
// Although type literal properties cannot not have initializers, we attempt
// to parse an initializer so we can report in the checker that an interface
// property or type literal property cannot have an initializer.
property.initializer = parseNonParameterInitializer();
}
parseTypeMemberSemicolon();
return finishNode(property);
}
@@ -4902,7 +4910,7 @@ namespace ts {
if (!decorators) {
decorators = <NodeArray<Decorator>>[];
decorators.pos = scanner.getStartPos();
decorators.pos = decoratorStart;
}
const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
@@ -5302,16 +5310,17 @@ namespace ts {
}
function parseModuleSpecifier(): Expression {
// We allow arbitrary expressions here, even though the grammar only allows string
// literals. We check to ensure that it is only a string literal later in the grammar
// walker.
const result = parseExpression();
// Ensure the string being required is in our 'identifier' table. This will ensure
// that features like 'find refs' will look inside this file when search for its name.
if (result.kind === SyntaxKind.StringLiteral) {
if (token === SyntaxKind.StringLiteral) {
const result = parseLiteralNode();
internIdentifier((<LiteralExpression>result).text);
return result;
}
else {
// We allow arbitrary expressions here, even though the grammar only allows string
// literals. We check to ensure that it is only a string literal later in the grammar
// check pass.
return parseExpression();
}
return result;
}
function parseNamespaceImport(): NamespaceImport {
@@ -5428,11 +5437,13 @@ namespace ts {
// reference comment.
while (true) {
const kind = triviaScanner.scan();
if (kind === SyntaxKind.WhitespaceTrivia || kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.MultiLineCommentTrivia) {
continue;
}
if (kind !== SyntaxKind.SingleLineCommentTrivia) {
break;
if (isTrivia(kind)) {
continue;
}
else {
break;
}
}
const range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
+8 -8
View File
@@ -661,19 +661,17 @@ namespace ts {
}
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
// For JavaScript files, we don't want to report the normal typescript semantic errors.
// Instead, we just report errors for using TypeScript-only constructs from within a
// JavaScript file.
if (isSourceFileJavaScript(sourceFile)) {
return getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken);
}
return runWithCancellationToken(() => {
const typeChecker = getDiagnosticsProducingTypeChecker();
Debug.assert(!!sourceFile.bindDiagnostics);
const bindDiagnostics = sourceFile.bindDiagnostics;
const checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
// For JavaScript files, we don't want to report the normal typescript semantic errors.
// Instead, we just report errors for using TypeScript-only constructs from within a
// JavaScript file.
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ?
getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) :
typeChecker.getDiagnostics(sourceFile, cancellationToken);
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
@@ -1079,6 +1077,8 @@ namespace ts {
const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
if (importedFile && resolution.isExternalLibraryImport) {
// Since currently irrespective of allowJs, we only look for supportedTypeScript extension external module files,
// this check is ok. Otherwise this would be never true for javascript file
if (!isExternalModule(importedFile)) {
const start = getTokenPosOfNode(file.imports[i], file);
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
+8 -2
View File
@@ -425,6 +425,12 @@ namespace ts {
/* @internal */
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
// Using ! with a greater than test is a fast way of testing the following conditions:
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
if (!(pos >= 0)) {
return pos;
}
// Keep in sync with couldStartTrivia
while (true) {
const ch = text.charCodeAt(pos);
@@ -567,12 +573,12 @@ namespace ts {
}
/**
* Extract comments from text prefixing the token closest following `pos`.
* Extract comments from text prefixing the token closest following `pos`.
* The return value is an array containing a TextRange for each comment.
* Single-line comment ranges include the beginning '//' characters but not the ending line break.
* Multi - line comment ranges include the beginning '/* and ending '<asterisk>/' characters.
* The return value is undefined if no comments were found.
* @param trailing
* @param trailing
* If false, whitespace is skipped until the first line break and comments between that location
* and the next token are returned.
* If true, comments occurring between the given position and the next line break are returned.
+332
View File
@@ -0,0 +1,332 @@
/// <reference path="checker.ts"/>
/* @internal */
namespace ts {
export interface SourceMapWriter {
getSourceMapData(): SourceMapData;
setSourceFile(sourceFile: SourceFile): void;
emitPos(pos: number): void;
emitStart(range: TextRange): void;
emitEnd(range: TextRange): void;
getText(): string;
getSourceMappingURL(): string;
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
reset(): void;
}
const nop = <(...args: any[]) => any>Function.prototype;
let nullSourceMapWriter: SourceMapWriter;
export function getNullSourceMapWriter(): SourceMapWriter {
if (nullSourceMapWriter === undefined) {
nullSourceMapWriter = {
getSourceMapData(): SourceMapData { return undefined; },
setSourceFile(sourceFile: SourceFile): void { },
emitStart(range: TextRange): void { },
emitEnd(range: TextRange): void { },
emitPos(pos: number): void { },
getText(): string { return undefined; },
getSourceMappingURL(): string { return undefined; },
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
reset(): void { },
};
}
return nullSourceMapWriter;
}
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
const compilerOptions = host.getCompilerOptions();
let currentSourceFile: SourceFile;
let sourceMapDir: string; // The directory in which sourcemap will be
// Current source map file and its index in the sources list
let sourceMapSourceIndex: number;
// Last recorded and encoded spans
let lastRecordedSourceMapSpan: SourceMapSpan;
let lastEncodedSourceMapSpan: SourceMapSpan;
let lastEncodedNameIndex: number;
// Source map data
let sourceMapData: SourceMapData;
return {
getSourceMapData: () => sourceMapData,
setSourceFile,
emitPos,
emitStart,
emitEnd,
getText,
getSourceMappingURL,
initialize,
reset,
};
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
if (sourceMapData) {
reset();
}
currentSourceFile = undefined;
// Current source map file and its index in the sources list
sourceMapSourceIndex = -1;
// Last recorded and encoded spans
lastRecordedSourceMapSpan = undefined;
lastEncodedSourceMapSpan = {
emittedLine: 1,
emittedColumn: 1,
sourceLine: 1,
sourceColumn: 1,
sourceIndex: 0
};
lastEncodedNameIndex = 0;
// Initialize source map data
sourceMapData = {
sourceMapFilePath: sourceMapFilePath,
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined,
sourceMapFile: getBaseFileName(normalizeSlashes(filePath)),
sourceMapSourceRoot: compilerOptions.sourceRoot || "",
sourceMapSources: [],
inputSourceFileNames: [],
sourceMapNames: [],
sourceMapMappings: "",
sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined,
sourceMapDecodedMappings: []
};
// Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
// relative paths of the sources list in the sourcemap
sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
sourceMapData.sourceMapSourceRoot += directorySeparator;
}
if (compilerOptions.mapRoot) {
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
if (!isBundledEmit) { // emitting single module file
Debug.assert(sourceFiles.length === 1);
// For modules or multiple emit files the mapRoot will have directory structure like the sources
// So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir));
}
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
// The relative paths are relative to the common directory
sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
getDirectoryPath(normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
host.getCurrentDirectory(),
host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true);
}
else {
sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
}
}
else {
sourceMapDir = getDirectoryPath(normalizePath(filePath));
}
}
function reset() {
currentSourceFile = undefined;
sourceMapDir = undefined;
sourceMapSourceIndex = undefined;
lastRecordedSourceMapSpan = undefined;
lastEncodedSourceMapSpan = undefined;
lastEncodedNameIndex = undefined;
sourceMapData = undefined;
}
// Encoding for sourcemap span
function encodeLastRecordedSourceMapSpan() {
if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
return;
}
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
// Line/Comma delimiters
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
// Emit comma to separate the entry
if (sourceMapData.sourceMapMappings) {
sourceMapData.sourceMapMappings += ",";
}
}
else {
// Emit line delimiters
for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
sourceMapData.sourceMapMappings += ";";
}
prevEncodedEmittedColumn = 1;
}
// 1. Relative Column 0 based
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
// 2. Relative sourceIndex
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
// 3. Relative sourceLine 0 based
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
// 4. Relative sourceColumn 0 based
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
// 5. Relative namePosition 0 based
if (lastRecordedSourceMapSpan.nameIndex >= 0) {
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
}
lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
}
function emitPos(pos: number) {
if (pos === -1) {
return;
}
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
// Convert the location to be one-based.
sourceLinePos.line++;
sourceLinePos.character++;
const emittedLine = writer.getLine();
const emittedColumn = writer.getColumn();
// If this location wasn't recorded or the location in source is going backwards, record the span
if (!lastRecordedSourceMapSpan ||
lastRecordedSourceMapSpan.emittedLine !== emittedLine ||
lastRecordedSourceMapSpan.emittedColumn !== emittedColumn ||
(lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
(lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
(lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
// Encode the last recordedSpan before assigning new
encodeLastRecordedSourceMapSpan();
// New span
lastRecordedSourceMapSpan = {
emittedLine: emittedLine,
emittedColumn: emittedColumn,
sourceLine: sourceLinePos.line,
sourceColumn: sourceLinePos.character,
sourceIndex: sourceMapSourceIndex
};
}
else {
// Take the new pos instead since there is no change in emittedLine and column since last location
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
}
}
function emitStart(range: TextRange) {
const rangeHasDecorators = !!(range as Node).decorators;
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
}
function emitEnd(range: TextRange) {
emitPos(range.end);
}
function setSourceFile(sourceFile: SourceFile) {
currentSourceFile = sourceFile;
// Add the file to tsFilePaths
// If sourceroot option: Use the relative path corresponding to the common directory path
// otherwise source locations relative to map file location
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
currentSourceFile.fileName,
host.getCurrentDirectory(),
host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true);
sourceMapSourceIndex = indexOf(sourceMapData.sourceMapSources, source);
if (sourceMapSourceIndex === -1) {
sourceMapSourceIndex = sourceMapData.sourceMapSources.length;
sourceMapData.sourceMapSources.push(source);
// The one that can be used from program to get the actual source file
sourceMapData.inputSourceFileNames.push(sourceFile.fileName);
if (compilerOptions.inlineSources) {
sourceMapData.sourceMapSourcesContent.push(sourceFile.text);
}
}
}
function getText() {
encodeLastRecordedSourceMapSpan();
return stringify({
version: 3,
file: sourceMapData.sourceMapFile,
sourceRoot: sourceMapData.sourceMapSourceRoot,
sources: sourceMapData.sourceMapSources,
names: sourceMapData.sourceMapNames,
mappings: sourceMapData.sourceMapMappings,
sourcesContent: sourceMapData.sourceMapSourcesContent,
});
}
function getSourceMappingURL() {
if (compilerOptions.inlineSourceMap) {
// Encode the sourceMap into the sourceMap url
const base64SourceMapText = convertToBase64(getText());
return sourceMapData.jsSourceMappingURL = `data:application/json;base64,${base64SourceMapText}`;
}
else {
return sourceMapData.jsSourceMappingURL;
}
}
}
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function base64FormatEncode(inValue: number) {
if (inValue < 64) {
return base64Chars.charAt(inValue);
}
throw TypeError(inValue + ": not a 64 based value");
}
function base64VLQFormatEncode(inValue: number) {
// Add a new least significant bit that has the sign of the value.
// if negative number the least significant bit that gets added to the number has value 1
// else least significant bit value that gets added is 0
// eg. -1 changes to binary : 01 [1] => 3
// +1 changes to binary : 01 [0] => 2
if (inValue < 0) {
inValue = ((-inValue) << 1) + 1;
}
else {
inValue = inValue << 1;
}
// Encode 5 bits at a time starting from least significant bits
let encodedStr = "";
do {
let currentDigit = inValue & 31; // 11111
inValue = inValue >> 5;
if (inValue > 0) {
// There are still more digits to decode, set the msb (6th bit)
currentDigit = currentDigit | 32;
}
encodedStr = encodedStr + base64FormatEncode(currentDigit);
} while (inValue > 0);
return encodedStr;
}
}
+54 -2
View File
@@ -47,6 +47,21 @@ namespace ts {
constructor(o: any);
}
declare var ChakraHost: {
args: string[];
currentDirectory: string;
executingFile: string;
echo(s: string): void;
quit(exitCode?: number): void;
fileExists(path: string): boolean;
directoryExists(path: string): boolean;
createDirectory(path: string): void;
resolvePath(path: string): string;
readFile(path: string): string;
writeFile(path: string, contents: string): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
};
export var sys: System = (function () {
function getWScriptSystem(): System {
@@ -194,6 +209,7 @@ namespace ts {
}
};
}
function getNodeSystem(): System {
const _fs = require("fs");
const _path = require("path");
@@ -281,7 +297,7 @@ namespace ts {
// REVIEW: for now this implementation uses polling.
// The advantage of polling is that it works reliably
// on all os and with network mounted files.
// For 90 referenced files, the average time to detect
// For 90 referenced files, the average time to detect
// changes is 2*msInterval (by default 5 seconds).
// The overhead of this is .04 percent (1/2500) with
// average pause of < 1 millisecond (and max
@@ -406,7 +422,7 @@ namespace ts {
};
},
watchDirectory: (path, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return _fs.watch(
path,
@@ -454,6 +470,37 @@ namespace ts {
}
};
}
function getChakraSystem(): System {
return {
newLine: "\r\n",
args: ChakraHost.args,
useCaseSensitiveFileNames: false,
write: ChakraHost.echo,
readFile(path: string, encoding?: string) {
// encoding is automatically handled by the implementation in ChakraHost
return ChakraHost.readFile(path);
},
writeFile(path: string, data: string, writeByteOrderMark?: boolean) {
// If a BOM is required, emit one
if (writeByteOrderMark) {
data = "\uFEFF" + data;
}
ChakraHost.writeFile(path, data);
},
resolvePath: ChakraHost.resolvePath,
fileExists: ChakraHost.fileExists,
directoryExists: ChakraHost.directoryExists,
createDirectory: ChakraHost.createDirectory,
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
readDirectory: ChakraHost.readDirectory,
exit: ChakraHost.quit,
};
}
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
return getWScriptSystem();
}
@@ -462,8 +509,13 @@ namespace ts {
// process.browser check excludes webpack and browserify
return getNodeSystem();
}
else if (typeof ChakraHost !== "undefined") {
return getChakraSystem();
}
else {
return undefined; // Unsupported host
}
})();
}
+9 -4
View File
@@ -439,12 +439,16 @@ namespace ts {
export const enum JsxFlags {
None = 0,
/** An element from a named property of the JSX.IntrinsicElements interface */
IntrinsicNamedElement = 1 << 0,
/** An element inferred from the string index signature of the JSX.IntrinsicElements interface */
IntrinsicIndexedElement = 1 << 1,
ClassElement = 1 << 2,
UnknownElement = 1 << 3,
/** An element backed by a class, class-like, or function value */
ValueElement = 1 << 2,
/** Element resolution failed */
UnknownElement = 1 << 4,
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement,
}
@@ -587,6 +591,7 @@ namespace ts {
name: PropertyName; // Declared property name
questionToken?: Node; // Present on optional property
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
// @kind(SyntaxKind.PropertyDeclaration)
@@ -1752,7 +1757,7 @@ namespace ts {
export interface SymbolDisplayBuilder {
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
+53 -19
View File
@@ -906,23 +906,6 @@ namespace ts {
return false;
}
export function childIsDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
}
return false;
}
export function nodeOrChildIsDecorated(node: Node): boolean {
return nodeIsDecorated(node) || childIsDecorated(node);
}
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression;
}
@@ -1906,8 +1889,10 @@ namespace ts {
* Resolves a local path to a path which is absolute to the base of the emit
*/
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string {
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
const relativePath = getRelativePathToDirectoryOrUrl(dir, fileName, dir, f => host.getCanonicalFileName(f), /*isAbsolutePathAnUrl*/ false);
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
const relativePath = getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
return removeFileExtension(relativePath);
}
@@ -2411,6 +2396,55 @@ namespace ts {
return output;
}
/**
* Serialize an object graph into a JSON string. This is intended only for use on an acyclic graph
* as the fallback implementation does not check for circular references by default.
*/
export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify
? JSON.stringify
: stringifyFallback;
/**
* Serialize an object graph into a JSON string.
*/
function stringifyFallback(value: any): string {
// JSON.stringify returns `undefined` here, instead of the string "undefined".
return value === undefined ? undefined : stringifyValue(value);
}
function stringifyValue(value: any): string {
return typeof value === "string" ? `"${escapeString(value)}"`
: typeof value === "number" ? isFinite(value) ? String(value) : "null"
: typeof value === "boolean" ? value ? "true" : "false"
: typeof value === "object" && value ? isArray(value) ? cycleCheck(stringifyArray, value) : cycleCheck(stringifyObject, value)
: /*fallback*/ "null";
}
function cycleCheck(cb: (value: any) => string, value: any) {
Debug.assert(!value.hasOwnProperty("__cycle"), "Converting circular structure to JSON");
value.__cycle = true;
const result = cb(value);
delete value.__cycle;
return result;
}
function stringifyArray(value: any) {
return `[${reduceLeft(value, stringifyElement, "")}]`;
}
function stringifyElement(memo: string, value: any) {
return (memo ? memo + "," : memo) + stringifyValue(value);
}
function stringifyObject(value: any) {
return `{${reduceProperties(value, stringifyProperty, "")}}`;
}
function stringifyProperty(memo: string, value: any, key: string) {
return value === undefined || typeof value === "function" || key === "__cycle" ? memo
: (memo ? memo + "," : memo) + `"${escapeString(key)}":${stringifyValue(value)}`;
}
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/**
+1 -1
View File
@@ -142,7 +142,7 @@ class CompilerBaselineRunner extends RunnerBase {
it("Correct JS output for " + fileName, () => {
if (hasNonDtsFiles && this.emit) {
if (result.files.length === 0 && result.errors.length === 0) {
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
}
+12 -4
View File
@@ -908,6 +908,7 @@ namespace Harness {
useCaseSensitiveFileNames?: boolean;
includeBuiltFile?: string;
baselineFile?: string;
libFiles?: string;
}
// Additional options not already in ts.optionDeclarations
@@ -917,6 +918,7 @@ namespace Harness {
{ name: "baselineFile", type: "string" },
{ name: "includeBuiltFile", type: "string" },
{ name: "fileName", type: "string" },
{ name: "libFiles", type: "string" },
{ name: "noErrorTruncation", type: "boolean" }
];
@@ -995,14 +997,11 @@ namespace Harness {
currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory();
// Parse settings
let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames();
if (harnessSettings) {
setCompilerOptionsFromHarnessSetting(harnessSettings, options);
}
if (options.useCaseSensitiveFileNames !== undefined) {
useCaseSensitiveFileNames = options.useCaseSensitiveFileNames;
}
const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames();
const programFiles: TestFile[] = inputFiles.slice();
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.
// Treat them as library files, so include them in build, but not in baselines.
@@ -1017,6 +1016,15 @@ namespace Harness {
const fileOutputs: GeneratedFile[] = [];
// Files from tests\lib that are requested by "@libFiles"
if (options.libFiles) {
for (const fileName of options.libFiles.split(",")) {
const libFileName = "tests/lib/" + fileName;
programFiles.push({ unitName: libFileName, content: normalizeLineEndings(IO.readFile(libFileName), Harness.IO.newLine()) });
}
}
const programFileNames = programFiles.map(file => file.unitName);
const compilerHost = createCompilerHost(
+1 -2
View File
@@ -172,7 +172,6 @@ namespace Harness.SourceMapRecoder {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// 5. Check if there is name:
decodeOfEncodedMapping.nameIndex = -1;
if (!isSourceMappingSegmentEnd()) {
prevNameIndex += base64VLQFormatDecode();
decodeOfEncodedMapping.nameIndex = prevNameIndex;
@@ -249,7 +248,7 @@ namespace Harness.SourceMapRecoder {
mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")";
}
else {
if (mapEntry.nameIndex !== -1 || getAbsentNameIndex) {
if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) {
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
}
}
+13 -10
View File
@@ -2058,6 +2058,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven
* Gets or sets the version attribute specified in the declaration of an XML document.
*/
xmlVersion: string;
currentScript: HTMLScriptElement;
adoptNode(source: Node): Node;
captureEvents(): void;
clear(): void;
@@ -2977,6 +2978,7 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
webkitRequestFullScreen(): void;
webkitRequestFullscreen(): void;
getElementsByClassName(classNames: string): NodeListOf<Element>;
matches(selector: string): boolean;
addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
@@ -3961,7 +3963,6 @@ interface HTMLElement extends Element {
title: string;
blur(): void;
click(): void;
contains(child: HTMLElement): boolean;
dragDrop(): boolean;
focus(): void;
insertAdjacentElement(position: string, insertedElement: Element): Element;
@@ -6135,7 +6136,7 @@ interface HTMLSelectElement extends HTMLElement {
* Sets or retrieves the name of the object.
*/
name: string;
options: HTMLSelectElement;
options: HTMLCollection;
/**
* When present, marks an element that can't be submitted without a value.
*/
@@ -6421,19 +6422,19 @@ interface HTMLTableElement extends HTMLElement {
/**
* Creates an empty caption element in the table.
*/
createCaption(): HTMLElement;
createCaption(): HTMLTableCaptionElement;
/**
* Creates an empty tBody element in the table.
*/
createTBody(): HTMLElement;
createTBody(): HTMLTableSectionElement;
/**
* Creates an empty tFoot element in the table.
*/
createTFoot(): HTMLElement;
createTFoot(): HTMLTableSectionElement;
/**
* Returns the tHead element object if successful, or null otherwise.
*/
createTHead(): HTMLElement;
createTHead(): HTMLTableSectionElement;
/**
* Deletes the caption element and its contents from the table.
*/
@@ -6455,7 +6456,7 @@ interface HTMLTableElement extends HTMLElement {
* Creates a new row (tr) in the table, and adds the row to the rows collection.
* @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
*/
insertRow(index?: number): HTMLElement;
insertRow(index?: number): HTMLTableRowElement;
}
declare var HTMLTableElement: {
@@ -6506,7 +6507,7 @@ interface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment {
* Creates a new cell in the table row, and adds the cell to the cells collection.
* @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.
*/
insertCell(index?: number): HTMLElement;
insertCell(index?: number): HTMLTableCellElement;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -6533,7 +6534,7 @@ interface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment {
* Creates a new row (tr) in the table, and adds the row to the rows collection.
* @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
*/
insertRow(index?: number): HTMLElement;
insertRow(index?: number): HTMLTableRowElement;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -7071,7 +7072,7 @@ declare var IDBVersionChangeEvent: {
}
interface ImageData {
data: number[];
data: Uint8ClampedArray;
height: number;
width: number;
}
@@ -7869,6 +7870,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte
getGamepads(): Gamepad[];
javaEnabled(): boolean;
msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
vibrate(pattern: number | number[]): boolean;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -7909,6 +7911,7 @@ interface Node extends EventTarget {
normalize(): void;
removeChild(oldChild: Node): Node;
replaceChild(newChild: Node, oldChild: Node): Node;
contains(node: Node): boolean;
ATTRIBUTE_NODE: number;
CDATA_SECTION_NODE: number;
COMMENT_NODE: number;
+1 -1
View File
@@ -460,7 +460,7 @@ declare var IDBVersionChangeEvent: {
}
interface ImageData {
data: number[];
data: Uint8ClampedArray;
height: number;
width: number;
}
+18 -3
View File
@@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
// Get previous token if the token is returned starts on new line
// eg: let x =10; |--- cursor is here
// let y = 10;
@@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
return spanInNode(tokenAtLocation);
function textSpan(startNode: Node, endNode?: Node) {
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
const start = startNode.decorators ?
skipTrivia(sourceFile.text, startNode.decorators.end) :
startNode.getStart(sourceFile);
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
}
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
return spanInNode(node);
}
return spanInNode(otherwiseOnNode);
}
function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
}
function spanInPreviousNode(node: Node): TextSpan {
return spanInNode(findPrecedingToken(node.pos, sourceFile));
}
@@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
return spanInPreviousNode(node);
}
if (node.parent.kind === SyntaxKind.Decorator) {
// Set breakpoint on the decorator emit
return spanInNode(node.parent);
}
if (node.parent.kind === SyntaxKind.ForStatement) {
// For now lets set the span on this expression, fix it later
return textSpan(node);
@@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
// span in statement
return spanInNode((<WithStatement>node).statement);
case SyntaxKind.Decorator:
return spanInNodeArray(node.parent.decorators);
// No breakpoint in interface, type alias
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
+24 -21
View File
@@ -1901,7 +1901,7 @@ namespace ts {
sourceMapText = text;
}
else {
Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
Debug.assert(outputText === undefined, `Unexpected multiple outputs for the file: '${name}'`);
outputText = text;
}
},
@@ -4248,28 +4248,31 @@ namespace ts {
}
else {
// Method/function type parameter
let container = getContainingFunction(location);
if (container) {
let signatureDeclaration = <SignatureDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
let declaration = <Node>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter);
Debug.assert(declaration !== undefined);
declaration = declaration.parent;
if (declaration) {
if (isFunctionLikeKind(declaration.kind)) {
const signature = typeChecker.getSignatureFromDeclaration(<SignatureDeclaration>declaration);
if (declaration.kind === SyntaxKind.ConstructSignature) {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
displayParts.push(spacePart());
}
else if (declaration.kind !== SyntaxKind.CallSignature && (<SignatureDeclaration>declaration).name) {
addFullSymbolName(declaration.symbol);
}
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
}
else {
// Type alias type parameter
// For example
// type list<T> = T[]; // Both T will go through same code path
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(declaration.symbol);
writeTypeParametersOfSymbol(declaration.symbol, sourceFile);
}
else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) {
addFullSymbolName(signatureDeclaration.symbol);
}
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
}
else {
// Type aliash type parameter
// For example
// type list<T> = T[]; // Both T will go through same code path
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(declaration.symbol);
writeTypeParametersOfSymbol(declaration.symbol, sourceFile);
}
}
}