mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-17 01:55:50 -06:00
type checking for pseudoiterable
This commit is contained in:
parent
74ec093d01
commit
bd867785bc
@ -10,6 +10,25 @@ namespace ts {
|
||||
let nextMergeId = 1;
|
||||
let nextFlowId = 1;
|
||||
|
||||
const enum EmitHelper {
|
||||
Extends = 1 << 0,
|
||||
Assign = 1 << 1,
|
||||
Decorate = 1 << 2,
|
||||
Metadata = 1 << 3,
|
||||
Param = 1 << 4,
|
||||
Awaiter = 1 << 5,
|
||||
Generator = 1 << 6,
|
||||
Values = 1 << 7,
|
||||
Step = 1 << 8,
|
||||
Close = 1 << 9,
|
||||
Read = 1 << 10,
|
||||
Spread = 1 << 11,
|
||||
ForOfIncludes = Values | Step | Close,
|
||||
SpreadIncludes = Read | Spread,
|
||||
FirstEmitHelper = Extends,
|
||||
LastEmitHelper = Spread
|
||||
}
|
||||
|
||||
export function getNodeId(node: Node): number {
|
||||
if (!node.id) {
|
||||
node.id = nextNodeId;
|
||||
@ -38,6 +57,8 @@ namespace ts {
|
||||
// is because diagnostics can be quite expensive, and we want to allow hosts to bail out if
|
||||
// they no longer need the information (for example, if the user started editing again).
|
||||
let cancellationToken: CancellationToken;
|
||||
let requestedExternalHelpers: EmitHelper;
|
||||
let externalHelpersModule: Symbol;
|
||||
|
||||
const Symbol = objectAllocator.getSymbolConstructor();
|
||||
const Type = objectAllocator.getTypeConstructor();
|
||||
@ -10430,7 +10451,7 @@ namespace ts {
|
||||
const index = indexOf(arrayLiteral.elements, node);
|
||||
return getTypeOfPropertyOfContextualType(type, "" + index)
|
||||
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|
||||
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false);
|
||||
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*checkAssignability*/ false);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -10649,6 +10670,10 @@ namespace ts {
|
||||
// with this type. It is neither affected by it, nor does it propagate it to its operand.
|
||||
// So the fact that contextualMapper is passed is not important, because the operand of a spread
|
||||
// element is not contextually typed.
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.SpreadIncludes);
|
||||
}
|
||||
|
||||
const arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
|
||||
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
|
||||
}
|
||||
@ -10679,7 +10704,7 @@ namespace ts {
|
||||
// if there is no index type / iterated type.
|
||||
const restArrayType = checkExpression((<SpreadElementExpression>e).expression, contextualMapper);
|
||||
const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
|
||||
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false);
|
||||
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*checkAssignability*/ false);
|
||||
if (restElementType) {
|
||||
elementTypes.push(restElementType);
|
||||
}
|
||||
@ -11024,6 +11049,10 @@ namespace ts {
|
||||
function checkJsxSpreadAttribute(node: JsxSpreadAttribute, elementAttributesType: Type, nameTable: Map<boolean>) {
|
||||
const type = checkExpression(node.expression);
|
||||
const props = getPropertiesOfType(type);
|
||||
if (compilerOptions.jsx === JsxEmit.React) {
|
||||
checkEmitHelpers(node, EmitHelper.Assign);
|
||||
}
|
||||
|
||||
for (const prop of props) {
|
||||
// Is there a corresponding property in the element attributes type? Skip checking of properties
|
||||
// that have already been assigned to, as these are not actually pushed into the resulting type
|
||||
@ -13791,6 +13820,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Read);
|
||||
}
|
||||
|
||||
// This elementType will be used if the specific property corresponding to this index is not
|
||||
// present (aka the tuple element property). This call also checks that the parentType is in
|
||||
// fact an iterable or array (depending on target language).
|
||||
@ -14206,6 +14239,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (node.asteriskToken && languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Values);
|
||||
}
|
||||
|
||||
if (node.expression) {
|
||||
const func = getContainingFunction(node);
|
||||
// If the user's code is syntactically correct, the func should always have a star. After all,
|
||||
@ -14666,6 +14703,17 @@ namespace ts {
|
||||
checkGrammarFunctionLikeDeclaration(<FunctionLikeDeclaration>node);
|
||||
}
|
||||
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
checkEmitHelpers(node, EmitHelper.Awaiter);
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Generator);
|
||||
}
|
||||
}
|
||||
|
||||
if (isSyntacticallyValidGenerator(node) && languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Generator);
|
||||
}
|
||||
|
||||
checkTypeParameters(node.typeParameters);
|
||||
|
||||
forEach(node.parameters, checkParameter);
|
||||
@ -15792,7 +15840,15 @@ namespace ts {
|
||||
error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning);
|
||||
}
|
||||
|
||||
checkEmitHelpers(node, EmitHelper.Decorate);
|
||||
|
||||
if (node.kind === SyntaxKind.Parameter) {
|
||||
checkEmitHelpers(node, EmitHelper.Param);
|
||||
}
|
||||
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
checkEmitHelpers(node, EmitHelper.Metadata);
|
||||
|
||||
// we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
@ -16374,6 +16430,10 @@ namespace ts {
|
||||
|
||||
// For a binding pattern, check contained binding elements
|
||||
if (isBindingPattern(node.name)) {
|
||||
if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Read);
|
||||
}
|
||||
|
||||
forEach((<BindingPattern>node.name).elements, checkSourceElement);
|
||||
}
|
||||
// For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
|
||||
@ -16545,6 +16605,10 @@ namespace ts {
|
||||
function checkForOfStatement(node: ForOfStatement): void {
|
||||
checkGrammarForInOrForOfStatement(node);
|
||||
|
||||
if (node.kind === SyntaxKind.ForOfStatement && languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.ForOfIncludes);
|
||||
}
|
||||
|
||||
// Check the LHS and RHS
|
||||
// If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS
|
||||
// via checkRightHandSideOfForOf.
|
||||
@ -16651,7 +16715,8 @@ namespace ts {
|
||||
if (isTypeAny(inputType)) {
|
||||
return inputType;
|
||||
}
|
||||
return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput) || unknownType;
|
||||
|
||||
return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, /*checkAssignability*/ true) || anyType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -16659,13 +16724,17 @@ namespace ts {
|
||||
* we want to get the iterated type of an iterable for ES2015 or later, or the iterated type
|
||||
* of a pseudo-iterable or element type of an array like for ES2015 or earlier.
|
||||
*/
|
||||
function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean): Type {
|
||||
function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, checkAssignability: boolean): Type {
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
return getIteratedTypeOfIterable(inputType, errorNode);
|
||||
const iteratedType = getIteratedTypeOfIterable(inputType, errorNode);
|
||||
if (checkAssignability && errorNode && iteratedType) {
|
||||
checkTypeAssignableTo(inputType, createIterableType(iteratedType), errorNode);
|
||||
}
|
||||
return iteratedType;
|
||||
}
|
||||
return allowStringInput
|
||||
? getIteratedTypeOfPseudoIterableOrElementTypeOfArrayOrString(inputType, errorNode)
|
||||
: getIteratedTypeOfPseudoIterableOrElementTypeOfArray(inputType, errorNode);
|
||||
? getIteratedTypeOfPseudoIterableOrElementTypeOfArrayOrString(inputType, errorNode, checkAssignability)
|
||||
: getIteratedTypeOfPseudoIterableOrElementTypeOfArray(inputType, errorNode, checkAssignability);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -16821,12 +16890,15 @@ namespace ts {
|
||||
* 1. Some constituent is neither a string nor an array.
|
||||
* 2. Some constituent is a string and target is less than ES5 (because in ES3 string is not indexable).
|
||||
*/
|
||||
function getIteratedTypeOfPseudoIterableOrElementTypeOfArrayOrString(arrayOrStringType: Type, errorNode: Node): Type {
|
||||
function getIteratedTypeOfPseudoIterableOrElementTypeOfArrayOrString(arrayOrStringType: Type, errorNode: Node, checkAssignability: boolean): Type {
|
||||
Debug.assert(languageVersion < ScriptTarget.ES2015);
|
||||
|
||||
const elementType = getIteratedTypeOfIterable(arrayOrStringType, /*errorNode*/ undefined);
|
||||
if (elementType) {
|
||||
return elementType;
|
||||
const iteratedType = getIteratedTypeOfIterable(arrayOrStringType, /*errorNode*/ undefined);
|
||||
if (iteratedType) {
|
||||
if (checkAssignability && errorNode) {
|
||||
checkTypeAssignableTo(arrayOrStringType, createIterableType(iteratedType), errorNode);
|
||||
}
|
||||
return iteratedType;
|
||||
}
|
||||
|
||||
// After we remove all types that are StringLike, we will know if there was a string constituent
|
||||
@ -16863,8 +16935,8 @@ namespace ts {
|
||||
// But if the input was just number, we want to say that number is not an array type
|
||||
// or a string type.
|
||||
const diagnostic = hasStringConstituent
|
||||
? Diagnostics.Type_0_is_not_an_array_type
|
||||
: Diagnostics.Type_0_is_not_an_array_type_or_a_string_type;
|
||||
? Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_an_iterator_method_that_returns_an_iterator
|
||||
: Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_an_iterator_method_that_returns_an_iterator;
|
||||
error(errorNode, diagnostic, typeToString(arrayType));
|
||||
}
|
||||
}
|
||||
@ -16884,18 +16956,21 @@ namespace ts {
|
||||
return arrayElementType;
|
||||
}
|
||||
|
||||
function getIteratedTypeOfPseudoIterableOrElementTypeOfArray(inputType: Type, errorNode: Node): Type {
|
||||
function getIteratedTypeOfPseudoIterableOrElementTypeOfArray(inputType: Type, errorNode: Node, checkAssignability: boolean): Type {
|
||||
Debug.assert(languageVersion < ScriptTarget.ES2015);
|
||||
|
||||
const elementType = getIteratedTypeOfIterable(inputType, /*errorNode*/ undefined);
|
||||
if (elementType) {
|
||||
return elementType;
|
||||
const iteratedType = getIteratedTypeOfIterable(inputType, /*errorNode*/ undefined);
|
||||
if (iteratedType) {
|
||||
if (checkAssignability && errorNode) {
|
||||
checkTypeAssignableTo(inputType, createIterableType(iteratedType), errorNode);
|
||||
}
|
||||
return iteratedType;
|
||||
}
|
||||
if (isArrayLikeType(inputType)) {
|
||||
return getIndexTypeOfType(inputType, IndexKind.Number);
|
||||
}
|
||||
if (errorNode) {
|
||||
error(errorNode, Diagnostics.Type_0_is_not_an_array_type, typeToString(inputType));
|
||||
error(errorNode, Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_an_iterator_method_that_returns_an_iterator, typeToString(inputType));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -17281,6 +17356,10 @@ namespace ts {
|
||||
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
checkEmitHelpers(node, EmitHelper.Extends);
|
||||
}
|
||||
|
||||
const baseTypes = getBaseTypes(type);
|
||||
if (baseTypes.length && produceDiagnostics) {
|
||||
const baseType = baseTypes[0];
|
||||
@ -19714,8 +19793,6 @@ namespace ts {
|
||||
|
||||
// Initialize global symbol table
|
||||
let augmentations: LiteralExpression[][];
|
||||
let requestedExternalEmitHelpers: NodeFlags = 0;
|
||||
let firstFileRequestingExternalHelpers: SourceFile;
|
||||
for (const file of host.getSourceFiles()) {
|
||||
if (!isExternalOrCommonJsModule(file)) {
|
||||
mergeSymbolTable(globals, file.locals);
|
||||
@ -19735,15 +19812,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((compilerOptions.isolatedModules || isExternalModule(file)) && !file.isDeclarationFile) {
|
||||
const fileRequestedExternalEmitHelpers = file.flags & NodeFlags.EmitHelperFlags;
|
||||
if (fileRequestedExternalEmitHelpers) {
|
||||
requestedExternalEmitHelpers |= fileRequestedExternalEmitHelpers;
|
||||
if (firstFileRequestingExternalHelpers === undefined) {
|
||||
firstFileRequestingExternalHelpers = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (augmentations) {
|
||||
@ -19808,53 +19876,55 @@ namespace ts {
|
||||
const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined);
|
||||
globalReadonlyArrayType = symbol && <GenericType>getTypeOfGlobalSymbol(symbol, /*arity*/ 1);
|
||||
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
|
||||
}
|
||||
|
||||
// If we have specified that we are importing helpers, we should report global
|
||||
// errors if we cannot resolve the helpers external module, or if it does not have
|
||||
// the necessary helpers exported.
|
||||
if (compilerOptions.importHelpers && firstFileRequestingExternalHelpers) {
|
||||
// Find the first reference to the helpers module.
|
||||
const helpersModule = resolveExternalModule(
|
||||
firstFileRequestingExternalHelpers,
|
||||
externalHelpersModuleNameText,
|
||||
Diagnostics.Cannot_find_module_0,
|
||||
/*errorNode*/ undefined);
|
||||
|
||||
// If we found the module, report errors if it does not have the necessary exports.
|
||||
if (helpersModule) {
|
||||
const exports = helpersModule.exports;
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES2015) {
|
||||
verifyHelperSymbol(exports, "__extends", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasJsxSpreadAttributes && compilerOptions.jsx !== JsxEmit.Preserve) {
|
||||
verifyHelperSymbol(exports, "__assign", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasDecorators) {
|
||||
verifyHelperSymbol(exports, "__decorate", SymbolFlags.Value);
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
verifyHelperSymbol(exports, "__metadata", SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasParamDecorators) {
|
||||
verifyHelperSymbol(exports, "__param", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
|
||||
verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
verifyHelperSymbol(exports, "__generator", SymbolFlags.Value);
|
||||
function checkEmitHelpers(node: Node, helpers: EmitHelper) {
|
||||
if ((requestedExternalHelpers & helpers) !== helpers && compilerOptions.importHelpers) {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
if (isEffectiveExternalModule(sourceFile, compilerOptions)) {
|
||||
const helpersModule = resolveHelpersModule(sourceFile);
|
||||
if (helpersModule !== unknownSymbol) {
|
||||
const uncheckedHelpers = helpers & ~requestedExternalHelpers;
|
||||
for (let helper = EmitHelper.FirstEmitHelper; helper <= EmitHelper.LastEmitHelper; helper <<= 1) {
|
||||
if (uncheckedHelpers & helper) {
|
||||
const name = getHelperName(helper);
|
||||
const symbol = getSymbol(helpersModule.exports, escapeIdentifier(name), SymbolFlags.Value);
|
||||
if (!symbol) {
|
||||
diagnostics.add(createFileDiagnostic(sourceFile, 0, 0, Diagnostics.Module_0_has_no_exported_member_1, externalHelpersModuleNameText, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
requestedExternalHelpers |= helpers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function verifyHelperSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags) {
|
||||
const symbol = getSymbol(symbols, escapeIdentifier(name), meaning);
|
||||
if (!symbol) {
|
||||
error(/*location*/ undefined, Diagnostics.Module_0_has_no_exported_member_1, externalHelpersModuleNameText, name);
|
||||
function getHelperName(helper: EmitHelper) {
|
||||
switch (helper) {
|
||||
case EmitHelper.Extends: return "__extends";
|
||||
case EmitHelper.Assign: return "__assign";
|
||||
case EmitHelper.Decorate: return "__decorate";
|
||||
case EmitHelper.Metadata: return "__metadata";
|
||||
case EmitHelper.Param: return "__param";
|
||||
case EmitHelper.Awaiter: return "__awaiter";
|
||||
case EmitHelper.Generator: return "__generator";
|
||||
case EmitHelper.Values: return "__values";
|
||||
case EmitHelper.Step: return "__step";
|
||||
case EmitHelper.Close: return "__close";
|
||||
case EmitHelper.Read: return "__read";
|
||||
case EmitHelper.Spread: return "__spread";
|
||||
}
|
||||
}
|
||||
|
||||
function resolveHelpersModule(node: SourceFile) {
|
||||
if (!externalHelpersModule) {
|
||||
externalHelpersModule = resolveExternalModule(node, externalHelpersModuleNameText, Diagnostics.Cannot_find_module_0, node) || unknownSymbol;
|
||||
}
|
||||
|
||||
return externalHelpersModule;
|
||||
}
|
||||
|
||||
function createInstantiatedPromiseLikeType(): ObjectType {
|
||||
const promiseLikeType = getGlobalPromiseLikeType();
|
||||
if (promiseLikeType !== emptyGenericType) {
|
||||
|
||||
@ -417,6 +417,8 @@ namespace ts {
|
||||
"webworker": "lib.webworker.d.ts",
|
||||
"scripthost": "lib.scripthost.d.ts",
|
||||
// ES2015 Or ESNext By-feature options
|
||||
"iterator": "lib.iterator.d.ts",
|
||||
"pseudoiterable": "lib.pseudoiterable.d.ts",
|
||||
"es2015.core": "lib.es2015.core.d.ts",
|
||||
"es2015.collection": "lib.es2015.collection.d.ts",
|
||||
"es2015.generator": "lib.es2015.generator.d.ts",
|
||||
|
||||
@ -1451,7 +1451,7 @@
|
||||
"category": "Error",
|
||||
"code": 2460
|
||||
},
|
||||
"Type '{0}' is not an array type.": {
|
||||
"Type '{0}' is not an array type or does not have an '__iterator__()' method that returns an iterator.": {
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
@ -1575,7 +1575,7 @@
|
||||
"category": "Error",
|
||||
"code": 2494
|
||||
},
|
||||
"Type '{0}' is not an array type or a string type.": {
|
||||
"Type '{0}' is not an array type or a string type or does not have an '__iterator__()' method that returns an iterator.": {
|
||||
"category": "Error",
|
||||
"code": 2495
|
||||
},
|
||||
|
||||
@ -1749,7 +1749,7 @@ namespace ts {
|
||||
text: `
|
||||
var __close = (this && this.__close) || function (r) {
|
||||
var m = !(r && r.done) && r.iterator["return"];
|
||||
if (m) m.call(r.iterator);
|
||||
if (m) return m.call(r.iterator);
|
||||
};`
|
||||
};
|
||||
|
||||
@ -1768,20 +1768,17 @@ namespace ts {
|
||||
scoped: false,
|
||||
text: `
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
var m = o.__iterator__;
|
||||
if (!m) return o;
|
||||
var r = { iterator: m.call(o) }, ar = [], e;
|
||||
try { while ((n === void 0 || n-- > 0) && __step(r)) ar.push(r.result.value); }
|
||||
if (!(m = o.__iterator__)) return o;
|
||||
var m, i = m.call(o), ar = [], r, e;
|
||||
try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); }
|
||||
catch (error) { e = { error: error }; }
|
||||
finally { try { __close(r); } finally { if (e) throw e.error; } }
|
||||
finally { try { if (m = !(r && r.done) && i["return"]) m.call(i); } finally { if (e) throw e.error; } }
|
||||
return ar;
|
||||
};`
|
||||
};
|
||||
|
||||
export function createReadHelper(context: TransformationContext, iteratorRecord: Expression, count: number | undefined, location?: TextRange) {
|
||||
context.requestEmitHelper(stepHelper);
|
||||
context.requestEmitHelper(readHelper);
|
||||
context.requestEmitHelper(closeHelper);
|
||||
return createCall(
|
||||
getHelperName("__read"),
|
||||
/*typeArguments*/ undefined,
|
||||
@ -1815,10 +1812,6 @@ namespace ts {
|
||||
|
||||
// Utilities
|
||||
|
||||
export function toFunctionBody(node: ConciseBody) {
|
||||
return isBlock(node) ? node : createBlock([createReturn(node, /*location*/ node)], /*location*/ node);
|
||||
}
|
||||
|
||||
export interface CallBinding {
|
||||
target: LeftHandSideExpression;
|
||||
thisArg: Expression;
|
||||
@ -1858,6 +1851,10 @@ namespace ts {
|
||||
thisArg = createThis();
|
||||
target = languageVersion < ScriptTarget.ES2015 ? createIdentifier("_super", /*location*/ callee) : <PrimaryExpression>callee;
|
||||
}
|
||||
else if (getEmitFlags(callee) & EmitFlags.HelperName) {
|
||||
thisArg = createVoidZero();
|
||||
target = parenthesizeForAccess(callee);
|
||||
}
|
||||
else {
|
||||
switch (callee.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression: {
|
||||
@ -2164,8 +2161,6 @@ namespace ts {
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
export function convertToFunctionBody(node: ConciseBody) {
|
||||
return isBlock(node) ? node : createBlock([createReturn(node, /*location*/ node)], /*location*/ node);
|
||||
}
|
||||
|
||||
@ -247,16 +247,30 @@ namespace ts {
|
||||
if (isEffectiveBindingPattern(bindingTarget)) {
|
||||
const elements = getElementsOfEffectiveBindingPattern(bindingTarget);
|
||||
const numElements = elements.length;
|
||||
if (isEffectiveObjectBindingPattern(bindingTarget)) {
|
||||
if (numElements !== 1) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(bindingElement) || numElements !== 0;
|
||||
boundValue = ensureIdentifier(boundValue, reuseIdentifierExpressions, emitTempVariableAssignment, location);
|
||||
}
|
||||
if (isEffectiveArrayBindingPattern(bindingTarget) && !isArrayLiteralExpression(boundValue)) {
|
||||
// Read the elements of the iterable into an array
|
||||
boundValue = emitTempVariableAssignment(
|
||||
createReadHelper(
|
||||
context,
|
||||
boundValue,
|
||||
isEffectiveBindingElementWithRest(elements[numElements - 1])
|
||||
? undefined
|
||||
: numElements,
|
||||
location
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
else if (numElements !== 1) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(bindingElement) || numElements !== 0;
|
||||
boundValue = ensureIdentifier(boundValue, reuseIdentifierExpressions, emitTempVariableAssignment, location);
|
||||
}
|
||||
|
||||
if (isEffectiveObjectBindingPattern(bindingTarget)) {
|
||||
for (const element of elements) {
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
flattenEffectiveBindingElement(
|
||||
@ -275,21 +289,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isArrayLiteralExpression(boundValue)) {
|
||||
// Read the elements of the iterable into an array
|
||||
boundValue = emitTempVariableAssignment(
|
||||
createReadHelper(
|
||||
context,
|
||||
boundValue,
|
||||
isEffectiveBindingElementWithRest(elements[numElements - 1])
|
||||
? undefined
|
||||
: numElements,
|
||||
location
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (isOmittedExpression(element)) {
|
||||
|
||||
@ -2079,7 +2079,8 @@ namespace ts {
|
||||
// evaluated on every iteration.
|
||||
const assignment = createAssignment(node.initializer, boundValue);
|
||||
if (isDestructuringAssignment(assignment)) {
|
||||
statements.push(visitNode(createStatement(assignment), visitor, isStatement));
|
||||
aggregateTransformFlags(assignment);
|
||||
statements.push(createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false)));
|
||||
}
|
||||
else {
|
||||
assignment.end = node.initializer.end;
|
||||
|
||||
@ -969,24 +969,29 @@ namespace ts {
|
||||
// ar = _a.concat([%sent%, 2]);
|
||||
|
||||
const numInitialElements = countInitialNodesWithoutYield(elements);
|
||||
const temp = declareLocal();
|
||||
let hasAssignedTemp = false;
|
||||
|
||||
let temp: Identifier;
|
||||
if (numInitialElements > 0) {
|
||||
temp = declareLocal();
|
||||
emitAssignment(temp,
|
||||
createArrayLiteral(
|
||||
visitNodes(elements, visitor, isExpression, 0, numInitialElements)
|
||||
)
|
||||
);
|
||||
hasAssignedTemp = true;
|
||||
}
|
||||
|
||||
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
|
||||
return hasAssignedTemp
|
||||
return temp
|
||||
? createArrayConcat(temp, [createArrayLiteral(expressions)])
|
||||
: createArrayLiteral(expressions);
|
||||
|
||||
function reduceElement(expressions: Expression[], element: Expression) {
|
||||
if (containsYield(element) && expressions.length > 0) {
|
||||
const hasAssignedTemp = temp !== undefined;
|
||||
if (!temp) {
|
||||
temp = declareLocal();
|
||||
}
|
||||
|
||||
emitAssignment(
|
||||
temp,
|
||||
hasAssignedTemp
|
||||
@ -996,7 +1001,6 @@ namespace ts {
|
||||
)
|
||||
: createArrayLiteral(expressions)
|
||||
);
|
||||
hasAssignedTemp = true;
|
||||
expressions = [];
|
||||
}
|
||||
|
||||
@ -1930,7 +1934,7 @@ namespace ts {
|
||||
|
||||
function cacheExpression(node: Expression): Identifier {
|
||||
let temp: Identifier;
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
if (isGeneratedIdentifier(node) || getEmitFlags(node) & EmitFlags.HelperName) {
|
||||
return <Identifier>node;
|
||||
}
|
||||
|
||||
|
||||
@ -3582,6 +3582,10 @@ namespace ts {
|
||||
return node.symbol && getDeclarationOfKind(node.symbol, kind) === node;
|
||||
}
|
||||
|
||||
export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions) {
|
||||
return isExternalModule(node) || compilerOptions.isolatedModules;
|
||||
}
|
||||
|
||||
// Node tests
|
||||
//
|
||||
// All node tests in the following list should *not* reference parent pointers so that
|
||||
|
||||
105
src/lib/es2015.iterable.d.ts
vendored
105
src/lib/es2015.iterable.d.ts
vendored
@ -1,24 +1,13 @@
|
||||
/// <reference path="lib.es2015.symbol.d.ts" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A method that returns the default iterator for an object. Called by the semantics of the
|
||||
/**
|
||||
* A method that returns the default iterator for an object. Called by the semantics of the
|
||||
* for-of statement.
|
||||
*/
|
||||
readonly iterator: symbol;
|
||||
}
|
||||
|
||||
interface IteratorResult<T> {
|
||||
done: boolean;
|
||||
value: T;
|
||||
}
|
||||
|
||||
interface Iterator<T> {
|
||||
next(value?: any): IteratorResult<T>;
|
||||
return?(value?: any): IteratorResult<T>;
|
||||
throw?(e?: any): IteratorResult<T>;
|
||||
}
|
||||
|
||||
interface Iterable<T> {
|
||||
[Symbol.iterator](): Iterator<T>;
|
||||
}
|
||||
@ -31,17 +20,17 @@ interface Array<T> {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<T>;
|
||||
@ -55,7 +44,7 @@ interface ArrayConstructor {
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param iterable An iterable object to convert to an array.
|
||||
@ -67,17 +56,17 @@ interface ReadonlyArray<T> {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<T>;
|
||||
@ -126,15 +115,15 @@ interface Promise<T> { }
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* Creates a Promise that is resolved with an array of results when all of the provided Promises
|
||||
* Creates a Promise that is resolved with an array of results when all of the provided Promises
|
||||
* resolve, or rejected when any Promise is rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
all<TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
|
||||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
|
||||
* or rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
@ -152,20 +141,20 @@ interface String {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
|
||||
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
|
||||
* number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int8Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -184,20 +173,20 @@ interface Int8ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint8Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -216,22 +205,22 @@ interface Uint8ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
|
||||
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
|
||||
* If the requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint8ClampedArray {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -251,22 +240,22 @@ interface Uint8ClampedArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int16Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -285,20 +274,20 @@ interface Int16ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint16Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -317,20 +306,20 @@ interface Uint16ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int32Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -349,20 +338,20 @@ interface Int32ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint32Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -386,15 +375,15 @@ interface Uint32ArrayConstructor {
|
||||
*/
|
||||
interface Float32Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
@ -413,20 +402,20 @@ interface Float32ArrayConstructor {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
|
||||
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
|
||||
* number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Float64Array {
|
||||
[Symbol.iterator](): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<number>;
|
||||
|
||||
10
src/lib/es5.d.ts
vendored
10
src/lib/es5.d.ts
vendored
@ -1338,11 +1338,6 @@ interface PromiseLike<T> {
|
||||
onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>;
|
||||
}
|
||||
|
||||
interface ArrayLike<T> {
|
||||
readonly length: number;
|
||||
readonly [n: number]: T;
|
||||
}
|
||||
|
||||
interface IteratorResult<T> {
|
||||
done: boolean;
|
||||
value: T;
|
||||
@ -1362,6 +1357,11 @@ interface PseudoIterableIterator<T> extends Iterator<T> {
|
||||
__iterator__(): PseudoIterableIterator<T>;
|
||||
}
|
||||
|
||||
interface ArrayLike<T> {
|
||||
readonly length: number;
|
||||
readonly [n: number]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a raw buffer of binary data, which is used to store data for the
|
||||
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user