diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b7937bb94b..fd1df17b507 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53,7 +53,6 @@ namespace ts { const compilerOptions = host.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); - const iterationMode = getEmitIterationMode(compilerOptions); const modulekind = getEmitModuleKind(compilerOptions); const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; @@ -11444,7 +11443,7 @@ namespace ts { } function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type { - if (languageVersion < ScriptTarget.ES2015 && iterationMode === IterationMode.Iterable) { + if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.SpreadIncludes); } @@ -14713,7 +14712,7 @@ namespace ts { } function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type { - if (languageVersion < ScriptTarget.ES2015 && iterationMode === IterationMode.Iterable) { + if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } @@ -15148,7 +15147,7 @@ namespace ts { checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegator); } } - else if (languageVersion < ScriptTarget.ES2015 && iterationMode === IterationMode.Iterable) { + else if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Values); } } @@ -17440,7 +17439,7 @@ namespace ts { // For a binding pattern, check contained binding elements if (isBindingPattern(node.name)) { - if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 && iterationMode === IterationMode.Iterable) { + if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } @@ -17622,7 +17621,7 @@ namespace ts { checkExternalEmitHelpers(node, ExternalEmitHelpers.ForAwaitOfIncludes); } } - else if (languageVersion < ScriptTarget.ES2015 && compilerOptions.iterationMode === IterationMode.Iterable) { + else if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ForOfIncludes); } } @@ -18061,7 +18060,7 @@ namespace ts { * 2. Some constituent is a string and target is less than ES5 (because in ES3 string is not indexable). */ function getIteratedTypeOfIterableOrElementTypeOfArrayOrString(arrayOrStringType: Type, errorNode: Node, checkAssignability: boolean): Type { - const iteratedType = iterationMode === IterationMode.Iterable && getIteratedTypeOfIterable(arrayOrStringType, /*errorNode*/ undefined); + const iteratedType = compilerOptions.downlevelIteration && getIteratedTypeOfIterable(arrayOrStringType, /*errorNode*/ undefined); if (iteratedType) { if (checkAssignability && errorNode) { checkTypeAssignableTo(arrayOrStringType, createIterableType(iteratedType), errorNode); @@ -18108,10 +18107,10 @@ 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 - ? iterationMode === IterationMode.Iterable + ? compilerOptions.downlevelIteration ? Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator : Diagnostics.Type_0_is_not_an_array_type - : iterationMode === IterationMode.Iterable + : compilerOptions.downlevelIteration ? Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator : Diagnostics.Type_0_is_not_an_array_type_or_a_string_type; error(errorNode, diagnostic, typeToString(arrayType)); @@ -18134,7 +18133,7 @@ namespace ts { } function getIteratedTypeOfIterableOrElementTypeOfArray(inputType: Type, errorNode: Node, checkAssignability: boolean): Type { - const iteratedType = iterationMode === IterationMode.Iterable && getIteratedTypeOfIterable(inputType, /*errorNode*/ undefined); + const iteratedType = compilerOptions.downlevelIteration && getIteratedTypeOfIterable(inputType, /*errorNode*/ undefined); if (iteratedType) { if (checkAssignability && errorNode) { checkTypeAssignableTo(inputType, createIterableType(iteratedType), errorNode); @@ -18145,7 +18144,7 @@ namespace ts { return getIndexTypeOfType(inputType, IndexKind.Number); } if (errorNode) { - const diagnostic = iterationMode === IterationMode.Iterable + const diagnostic = compilerOptions.downlevelIteration ? Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator : Diagnostics.Type_0_is_not_an_array_type; error(errorNode, diagnostic, typeToString(inputType)); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index b1bbb9b9955..dd0b495f191 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -333,13 +333,9 @@ namespace ts { description: Diagnostics.Disallow_inconsistently_cased_references_to_the_same_file }, { - name: "iterationMode", - type: createMap({ - "array": IterationMode.Array, - "iterable": IterationMode.Iterable - }), - description: Diagnostics.Specify_how_to_emit_for_of_spread_and_destructuring_in_ES5_Slash3_Colon_array_arrays_only_default_or_iterable_support_arrays_and_Symbol_iterator, - paramType: Diagnostics.MODE + name: "downlevelIteration", + type: "boolean", + description: Diagnostics.Use_full_down_level_iteration_for_iterables_and_arrays_for_for_of_spread_and_destructuring_in_ES5_Slash3 }, { name: "baseUrl", diff --git a/src/compiler/core.ts b/src/compiler/core.ts index a809a821742..2daf5c4e564 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1373,10 +1373,6 @@ namespace ts { getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; } - export function getEmitIterationMode(compilerOptions: CompilerOptions) { - return getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? IterationMode.Iterable : compilerOptions.iterationMode || IterationMode.Array; - } - export function getEmitModuleResolutionKind(compilerOptions: CompilerOptions) { let moduleResolution = compilerOptions.moduleResolution; if (moduleResolution === undefined) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 431485aa54d..c98badb188b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2597,10 +2597,6 @@ "category": "Message", "code": 6039 }, - "MODE": { - "category": "Message", - "code": 6040 - }, "Compilation complete. Watching for file changes.": { "category": "Message", "code": 6042 @@ -3009,7 +3005,7 @@ "category": "Message", "code": 6148 }, - "Specify how to emit for-of, spread, and destructuring in ES5/3: 'array' (arrays only; default) or 'iterable' (support arrays and Symbol.iterator)": { + "Use full down-level iteration for iterables and arrays for 'for-of', spread, and destructuring in ES5/3.": { "category": "Message", "code": 6149 }, diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index bba71cd1743..bd2d00d3171 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -6,7 +6,7 @@ namespace ts { interface FlattenContext { context: TransformationContext; level: FlattenLevel; - iterationMode: IterationMode; + downlevelIteration: boolean; hoistTempVariables: boolean; emitExpression: (value: Expression) => void; emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void; @@ -58,7 +58,7 @@ namespace ts { const flattenContext: FlattenContext = { context, level, - iterationMode: getEmitIterationMode(context.getCompilerOptions()), + downlevelIteration: context.getCompilerOptions().downlevelIteration, hoistTempVariables: true, emitExpression, emitBindingOrAssignment, @@ -145,7 +145,7 @@ namespace ts { const flattenContext: FlattenContext = { context, level, - iterationMode: getEmitIterationMode(context.getCompilerOptions()), + downlevelIteration: context.getCompilerOptions().downlevelIteration, hoistTempVariables, emitExpression, emitBindingOrAssignment, @@ -311,7 +311,7 @@ namespace ts { function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ArrayBindingOrAssignmentPattern, value: Expression, location: TextRange) { const elements = getElementsOfBindingOrAssignmentPattern(pattern); const numElements = elements.length; - if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.iterationMode === IterationMode.Iterable) { + if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.downlevelIteration) { // Read the elements of the iterable into an array value = ensureIdentifier( flattenContext, diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 08d1f46142c..190ac0023c4 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -270,7 +270,6 @@ namespace ts { } = context; const compilerOptions = context.getCompilerOptions(); - const iterationMode = getEmitIterationMode(compilerOptions); const resolver = context.getEmitResolver(); const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; @@ -2200,7 +2199,7 @@ namespace ts { HierarchyFacts.ForInOrForOfStatementIncludes, node, outermostLabeledStatement, - iterationMode === IterationMode.Array ? convertForOfStatementForArray : convertForOfStatementForIterable); + compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); } function convertForOfStatementHead(statements: Statement[], node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) { @@ -3330,7 +3329,7 @@ namespace ts { ) ); - if (iterationMode === IterationMode.Iterable) { + if (compilerOptions.downlevelIteration) { if (segments.length === 1) { const firstSegment = segments[0]; if (isCallExpression(firstSegment) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1a684b84922..e44082b2b30 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3151,11 +3151,6 @@ namespace ts { NodeJs = 2 } - export enum IterationMode { - Array, - Iterable - } - export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike; export interface CompilerOptions { @@ -3173,11 +3168,11 @@ namespace ts { /* @internal */ diagnostics?: boolean; /* @internal */ extendedDiagnostics?: boolean; disableSizeLimit?: boolean; + downlevelIteration?: boolean; emitBOM?: boolean; emitDecoratorMetadata?: boolean; experimentalDecorators?: boolean; forceConsistentCasingInFileNames?: boolean; - iterationMode?: IterationMode; /*@internal*/help?: boolean; importHelpers?: boolean; /*@internal*/init?: boolean; diff --git a/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment1ES5iterable.ts b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment1ES5iterable.ts index eac4a0bf665..14c46d4d984 100644 --- a/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment1ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment1ES5iterable.ts @@ -1,4 +1,4 @@ -// @iterationMode: iterable +// @downlevelIteration: true /* AssignmentPattern: * ObjectAssignmentPattern * ArrayAssignmentPattern diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts index 381dd47d3eb..dac4bc5b116 100644 --- a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts @@ -1,4 +1,4 @@ -// @iterationMode: iterable +// @downlevelIteration: true // A parameter declaration may specify either an identifier or a binding pattern. // The identifiers specified in parameter declarations and binding patterns // in a parameter list must be unique within that parameter list. diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts index e919526a459..53b79c04471 100644 --- a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts @@ -1,5 +1,5 @@ // @target: es5 -// @iterationMode: iterable +// @downlevelIteration: true // If the parameter is a rest parameter, the parameter type is any[] // A type annotation for a rest parameter must denote an array type. diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5iterable.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5iterable.ts index cbef9355d66..530999eadd2 100644 --- a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5iterable.ts @@ -1,5 +1,5 @@ // @target: es5 -// @iterationMode: iterable +// @downlevelIteration: true interface ISomething { foo: string, diff --git a/tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration1ES5iterable.ts b/tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration1ES5iterable.ts index 6d71f960877..ab475575b43 100644 --- a/tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration1ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration1ES5iterable.ts @@ -1,4 +1,4 @@ -// @iterationMode: iterable +// @downlevelIteration: true // The type T associated with a destructuring variable declaration is determined as follows: // If the declaration includes a type annotation, T is that type. var {a1, a2}: { a1: number, a2: string } = { a1: 10, a2: "world" } diff --git a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns01_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns01_ES5iterable.ts index 26b8e528219..247da5a0de0 100644 --- a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns01_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns01_ES5iterable.ts @@ -1,6 +1,6 @@ // @target: es5 // @declaration: true -// @iterationMode: iterable +// @downlevelIteration: true var a: any; diff --git a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns02_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns02_ES5iterable.ts index 6e08bd7b152..0aa7bf24196 100644 --- a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns02_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns02_ES5iterable.ts @@ -1,6 +1,6 @@ // @target: es5 // @declaration: true -// @iterationMode: iterable +// @downlevelIteration: true var a: any; let x, y, z, a1, a2, a3; diff --git a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns03_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns03_ES5iterable.ts index 799208853f1..f42adc0007f 100644 --- a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns03_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns03_ES5iterable.ts @@ -1,6 +1,6 @@ // @target: es5 // @declaration: true -// @iterationMode: iterable +// @downlevelIteration: true var a: any; diff --git a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns04_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns04_ES5iterable.ts index c9a5e0765c3..5b6024e1d41 100644 --- a/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns04_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyAssignmentPatterns04_ES5iterable.ts @@ -1,6 +1,6 @@ // @target: es5 // @declaration: true -// @iterationMode: iterable +// @downlevelIteration: true var a: any; let x, y, z, a1, a2, a3; diff --git a/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns01_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns01_ES5iterable.ts index 8a85c91746d..07542e42ee6 100644 --- a/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns01_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns01_ES5iterable.ts @@ -1,5 +1,5 @@ // @target: es5 -// @iterationMode: iterable +// @downlevelIteration: true (function () { var a: any; diff --git a/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns02_ES5iterable.ts b/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns02_ES5iterable.ts index bd991072ae9..e9a04caf04f 100644 --- a/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns02_ES5iterable.ts +++ b/tests/cases/conformance/es6/destructuring/emptyVariableDeclarationBindingPatterns02_ES5iterable.ts @@ -1,6 +1,6 @@ // @target: es5 // @declaration: true -// @iterationMode: iterable +// @downlevelIteration: true (function () { var {}; diff --git a/tests/cases/conformance/es6/spread/arrayLiteralSpreadES5iterable.ts b/tests/cases/conformance/es6/spread/arrayLiteralSpreadES5iterable.ts index eb1566ad1df..e6fedbc2e5f 100644 --- a/tests/cases/conformance/es6/spread/arrayLiteralSpreadES5iterable.ts +++ b/tests/cases/conformance/es6/spread/arrayLiteralSpreadES5iterable.ts @@ -1,4 +1,4 @@ -// @iterationMode: iterable +// @downlevelIteration: true function f0() { var a = [1, 2, 3]; var a1 = [...a]; diff --git a/tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts b/tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts index 33116b0ec67..0bf68baf029 100644 --- a/tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts +++ b/tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts @@ -1,5 +1,5 @@ //@sourcemap: true -//@iterationMode: iterable +//@downlevelIteration: true for (var v of ['a', 'b', 'c']) { console.log(v); } \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts b/tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts index 17aad2319f8..b10214199ae 100644 --- a/tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts +++ b/tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts @@ -1,5 +1,5 @@ //@sourcemap: true -//@iterationMode: iterable +//@downlevelIteration: true function foo() { return { x: 0 }; } diff --git a/tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts b/tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts index d3143861197..106b307333e 100644 --- a/tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts +++ b/tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts @@ -1,5 +1,5 @@ //@sourcemap: true -//@iterationMode: iterable +//@downlevelIteration: true for (const {x: a = 0, y: b = 1} of [2, 3]) { a; b; diff --git a/tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts b/tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts index 0a09632b0ec..1aff61c99dd 100644 --- a/tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts +++ b/tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts @@ -1,5 +1,5 @@ //@sourcemap: true -//@iterationMode: iterable +//@downlevelIteration: true for (let [a = 0, b = 1] of [2, 3]) { a; b;