diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 04049238661..e1ea3e21de0 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -144,6 +144,7 @@ module ts { Array_element_destructuring_pattern_expected: { code: 1181, category: DiagnosticCategory.Error, key: "Array element destructuring pattern expected." }, A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." }, Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." }, + A_rest_element_cannot_have_an_initializer: { code: 1184, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6663ff057b8..6b4274fbc5d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -568,6 +568,10 @@ "category": "Error", "code": 1183 }, + "A rest element cannot have an initializer.": { + "category": "Error", + "code": 1184 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 239a89c6694..2fcdd876864 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3022,8 +3022,17 @@ module ts { emitBindingElement(element, createPropertyAccess(value, propName)); } else if (element.kind !== SyntaxKind.OmittedExpression) { - // Rewrite element to a declaration that accesses array element at index i - emitBindingElement(element, createElementAccess(value, createNumericLiteral(i))); + if (!element.dotDotDotToken) { + // Rewrite element to a declaration that accesses array element at index i + emitBindingElement(element, createElementAccess(value, createNumericLiteral(i))); + } + else { + if (i === elements.length - 1) { + value = ensureIdentifier(value); + emitAssignment(element.name, value); + write(".slice(" + i + ")"); + } + } } } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 89467ba456f..94cab916a05 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1585,7 +1585,7 @@ module ts { case ParsingContext.VariableDeclarations: return isIdentifierOrPattern(); case ParsingContext.ArrayBindingElements: - return token === SyntaxKind.CommaToken || isIdentifierOrPattern(); + return token === SyntaxKind.CommaToken || token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern(); case ParsingContext.TypeParameters: return isIdentifier(); case ParsingContext.ArgumentExpressions: @@ -3886,6 +3886,7 @@ module ts { } } else { + node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); node.name = parseIdentifierOrPattern(); } node.initializer = parseInitializer(/*inParameter*/ false); @@ -5748,6 +5749,16 @@ module ts { } function checkBindingElement(node: BindingElement) { + if (node.dotDotDotToken) { + var elements = (node.parent).elements; + if (node !== elements[elements.length - 1]) { + return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern); + } + if (node.initializer) { + // Error on equals token which immediate precedes the initializer + return grammarErrorAtPos(node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer); + } + } if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.name)) { // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code // and its Identifier is eval or arguments