mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-12 03:20:56 -06:00
commit
25462c9571
@ -1918,6 +1918,9 @@ namespace ts {
|
||||
return bindParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
if ((node as BindingElement).dotDotDotToken && node.parent.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
emitFlags |= NodeFlags.HasRestAttribute;
|
||||
}
|
||||
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
@ -1933,7 +1936,19 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
emitFlags |= NodeFlags.HasSpreadAttribute;
|
||||
let root = container;
|
||||
let hasRest = false;
|
||||
while (root.parent) {
|
||||
if (root.kind === SyntaxKind.ObjectLiteralExpression &&
|
||||
root.parent.kind === SyntaxKind.BinaryExpression &&
|
||||
(root.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
(root.parent as BinaryExpression).left === root) {
|
||||
hasRest = true;
|
||||
break;
|
||||
}
|
||||
root = root.parent;
|
||||
}
|
||||
emitFlags |= hasRest ? NodeFlags.HasRestAttribute : NodeFlags.HasSpreadAttribute;
|
||||
return;
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
@ -2544,10 +2559,13 @@ namespace ts {
|
||||
const operatorTokenKind = node.operatorToken.kind;
|
||||
const leftKind = node.left.kind;
|
||||
|
||||
if (operatorTokenKind === SyntaxKind.EqualsToken
|
||||
&& (leftKind === SyntaxKind.ObjectLiteralExpression
|
||||
|| leftKind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
// Destructuring assignments are ES6 syntax.
|
||||
if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// Destructuring object assignments with are ES2015 syntax
|
||||
// and possibly ESNext if they contain rest
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ArrayLiteralExpression) {
|
||||
// Destructuring assignments are ES2015 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken
|
||||
@ -2581,6 +2599,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
|
||||
}
|
||||
|
||||
// parameters with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
|
||||
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
|
||||
if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) {
|
||||
@ -2814,6 +2837,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a FunctionDeclaration's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
@ -2851,6 +2879,12 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function expressions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
|
||||
// If a FunctionExpression's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
@ -2888,6 +2922,11 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// arrow functions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
|
||||
@ -2916,8 +2955,13 @@ namespace ts {
|
||||
let transformFlags = subtreeFlags;
|
||||
const nameKind = node.name.kind;
|
||||
|
||||
// A VariableDeclaration with a binding pattern is ES6 syntax.
|
||||
if (nameKind === SyntaxKind.ObjectBindingPattern || nameKind === SyntaxKind.ArrayBindingPattern) {
|
||||
// A VariableDeclaration with an object binding pattern is ES2015 syntax
|
||||
// and possibly ESNext syntax if it contains an object binding pattern
|
||||
if (nameKind === SyntaxKind.ObjectBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
// A VariableDeclaration with an object binding pattern is ES2015 syntax.
|
||||
else if (nameKind === SyntaxKind.ArrayBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
|
||||
@ -3058,6 +3102,10 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// for-of might be ESNext if it has a rest destructuring
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
// FALLTHROUGH
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
@ -3065,7 +3113,6 @@ namespace ts {
|
||||
case SyntaxKind.TemplateExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.StaticKeyword:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@ -3131,10 +3178,16 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
// This node is ES6 or ES future syntax, but is handled by a containing node.
|
||||
// This node is ES6 or ES next syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadExpression;
|
||||
break;
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
if ((node as BindingElement).dotDotDotToken) {
|
||||
// this node is ES2015 or ES next syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadExpression;
|
||||
}
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@ -3147,8 +3200,13 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
// These nodes are ES2015 or ES Next syntax.
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
else {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
|
||||
@ -2982,26 +2982,31 @@ namespace ts {
|
||||
return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false);
|
||||
}
|
||||
|
||||
function getTextOfPropertyName(name: PropertyName): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return (<Identifier>name).text;
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return (<LiteralExpression>name).text;
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
|
||||
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isComputedNonLiteralName(name: PropertyName): boolean {
|
||||
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind);
|
||||
}
|
||||
|
||||
function getRestType(source: Type, properties: PropertyName[], symbol: Symbol): Type {
|
||||
Debug.assert(!!(source.flags & TypeFlags.Object), "Rest types only support object types right now.");
|
||||
const members = createMap<Symbol>();
|
||||
const names = createMap<true>();
|
||||
for (const name of properties) {
|
||||
names[getTextOfPropertyName(name)] = true;
|
||||
}
|
||||
for (const prop of getPropertiesOfType(source)) {
|
||||
const inNamesToRemove = prop.name in names;
|
||||
const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected);
|
||||
const isMethod = prop.flags & SymbolFlags.Method;
|
||||
const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
|
||||
if (!inNamesToRemove && !isPrivate && !isMethod && !isSetOnlyAccessor) {
|
||||
members[prop.name] = prop;
|
||||
}
|
||||
}
|
||||
const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number);
|
||||
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
}
|
||||
|
||||
/** Return the inferred type for a binding element */
|
||||
function getTypeForBindingElement(declaration: BindingElement): Type {
|
||||
const pattern = <BindingPattern>declaration.parent;
|
||||
@ -3022,26 +3027,41 @@ namespace ts {
|
||||
|
||||
let type: Type;
|
||||
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
|
||||
const name = declaration.propertyName || <Identifier>declaration.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// computed properties with non-literal names are treated as 'any'
|
||||
return anyType;
|
||||
}
|
||||
if (declaration.initializer) {
|
||||
getContextualType(declaration.initializer);
|
||||
if (declaration.dotDotDotToken) {
|
||||
if (!(parentType.flags & TypeFlags.Object)) {
|
||||
error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
|
||||
return unknownType;
|
||||
}
|
||||
const literalMembers: PropertyName[] = [];
|
||||
for (const element of pattern.elements) {
|
||||
if (element.kind !== SyntaxKind.OmittedExpression && !(element as BindingElement).dotDotDotToken) {
|
||||
literalMembers.push(element.propertyName || element.name as Identifier);
|
||||
}
|
||||
}
|
||||
type = getRestType(parentType, literalMembers, declaration.symbol);
|
||||
}
|
||||
else {
|
||||
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
|
||||
const name = declaration.propertyName || <Identifier>declaration.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// computed properties with non-literal names are treated as 'any'
|
||||
return anyType;
|
||||
}
|
||||
if (declaration.initializer) {
|
||||
getContextualType(declaration.initializer);
|
||||
}
|
||||
|
||||
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
|
||||
// or otherwise the type of the string index signature.
|
||||
const text = getTextOfPropertyName(name);
|
||||
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
|
||||
// or otherwise the type of the string index signature.
|
||||
const text = getTextOfPropertyName(name);
|
||||
|
||||
type = getTypeOfPropertyOfType(parentType, text) ||
|
||||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(parentType, IndexKind.String);
|
||||
if (!type) {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
|
||||
return unknownType;
|
||||
type = getTypeOfPropertyOfType(parentType, text) ||
|
||||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(parentType, IndexKind.String);
|
||||
if (!type) {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3249,8 +3269,8 @@ namespace ts {
|
||||
let hasComputedProperties = false;
|
||||
forEach(pattern.elements, e => {
|
||||
const name = e.propertyName || <Identifier>e.name;
|
||||
if (isComputedNonLiteralName(name)) {
|
||||
// do not include computed properties in the implied type
|
||||
if (isComputedNonLiteralName(name) || e.dotDotDotToken) {
|
||||
// do not include computed properties or rests in the implied type
|
||||
hasComputedProperties = true;
|
||||
return;
|
||||
}
|
||||
@ -13889,7 +13909,7 @@ namespace ts {
|
||||
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (property.kind !== SyntaxKind.SpreadAssignment) {
|
||||
error(property, Diagnostics.Property_assignment_expected);
|
||||
}
|
||||
}
|
||||
@ -13935,7 +13955,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
if (elementIndex < elements.length - 1) {
|
||||
error(element, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
|
||||
}
|
||||
else {
|
||||
const restExpression = (<SpreadElement>element).expression;
|
||||
@ -20832,7 +20852,7 @@ namespace ts {
|
||||
if (node.dotDotDotToken) {
|
||||
const elements = (<BindingPattern>node.parent).elements;
|
||||
if (node !== lastOrUndefined(elements)) {
|
||||
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
|
||||
return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
|
||||
}
|
||||
|
||||
if (node.name.kind === SyntaxKind.ArrayBindingPattern || node.name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
|
||||
@ -1455,7 +1455,7 @@
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
"A rest element must be last in an array destructuring pattern": {
|
||||
"A rest element must be last in a destructuring pattern": {
|
||||
"category": "Error",
|
||||
"code": 2462
|
||||
},
|
||||
@ -1987,6 +1987,10 @@
|
||||
"category": "Error",
|
||||
"code": 2698
|
||||
},
|
||||
"Rest types may only be created from object types.": {
|
||||
"category": "Error",
|
||||
"code": 2700
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -42,6 +42,14 @@ var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
return t;
|
||||
};`;
|
||||
|
||||
const restHelper = `
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};`;
|
||||
|
||||
// emit output for the __decorate helper function
|
||||
const decorateHelper = `
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
@ -226,6 +234,7 @@ const _super = (function (geti, seti) {
|
||||
let currentFileIdentifiers: Map<string>;
|
||||
let extendsEmitted: boolean;
|
||||
let assignEmitted: boolean;
|
||||
let restEmitted: boolean;
|
||||
let decorateEmitted: boolean;
|
||||
let paramEmitted: boolean;
|
||||
let awaiterEmitted: boolean;
|
||||
@ -2222,6 +2231,11 @@ const _super = (function (geti, seti) {
|
||||
assignEmitted = true;
|
||||
}
|
||||
|
||||
if (languageVersion < ScriptTarget.ESNext && !restEmitted && node.flags & NodeFlags.HasRestAttribute) {
|
||||
writeLines(restHelper);
|
||||
restEmitted = true;
|
||||
}
|
||||
|
||||
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
|
||||
writeLines(decorateHelper);
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
|
||||
@ -3068,4 +3068,538 @@ namespace ts {
|
||||
function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
|
||||
return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the body of a function-like node.
|
||||
*
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
export function transformFunctionBody(node: FunctionLikeDeclaration,
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
currentSourceFile: SourceFile,
|
||||
context: TransformationContext,
|
||||
enableSubstitutionsForCapturedThis: () => void,
|
||||
convertObjectRest?: boolean) {
|
||||
let multiLine = false; // indicates whether the block *must* be emitted as multiple lines
|
||||
let singleLine = false; // indicates whether the block *may* be emitted as a single line
|
||||
let statementsLocation: TextRange;
|
||||
let closeBraceLocation: TextRange;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body;
|
||||
let statementOffset: number;
|
||||
|
||||
context.startLexicalEnvironment();
|
||||
if (isBlock(body)) {
|
||||
// ensureUseStrict is false because no new prologue-directive should be added.
|
||||
// addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
}
|
||||
|
||||
addCaptureThisForNodeIfNeeded(statements, node, enableSubstitutionsForCapturedThis);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, node, visitor, convertObjectRest);
|
||||
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
|
||||
// If we added any generated statements, this must be a multi-line block.
|
||||
if (!multiLine && statements.length > 0) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
if (isBlock(body)) {
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
|
||||
|
||||
// If the original body was a multi-line block, this must be a multi-line block.
|
||||
if (!multiLine && body.multiLine) {
|
||||
multiLine = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assert(node.kind === SyntaxKind.ArrowFunction);
|
||||
|
||||
// To align with the old emitter, we use a synthetic end position on the location
|
||||
// for the statement list we synthesize when we down-level an arrow function with
|
||||
// an expression function body. This prevents both comments and source maps from
|
||||
// being emitted for the end position only.
|
||||
statementsLocation = moveRangeEnd(body, -1);
|
||||
|
||||
const equalsGreaterThanToken = (<ArrowFunction>node).equalsGreaterThanToken;
|
||||
if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) {
|
||||
if (rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) {
|
||||
singleLine = true;
|
||||
}
|
||||
else {
|
||||
multiLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
const expression = visitNode(body, visitor, isExpression);
|
||||
const returnStatement = createReturn(expression, /*location*/ body);
|
||||
setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments);
|
||||
statements.push(returnStatement);
|
||||
|
||||
// To align with the source map emit for the old emitter, we set a custom
|
||||
// source map location for the close brace.
|
||||
closeBraceLocation = body;
|
||||
}
|
||||
|
||||
const lexicalEnvironment = context.endLexicalEnvironment();
|
||||
addRange(statements, lexicalEnvironment);
|
||||
|
||||
// If we added any final generated statements, this must be a multi-line block
|
||||
if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine);
|
||||
if (!multiLine && singleLine) {
|
||||
setEmitFlags(block, EmitFlags.SingleLine);
|
||||
}
|
||||
|
||||
if (closeBraceLocation) {
|
||||
setTokenSourceMapRange(block, SyntaxKind.CloseBraceToken, closeBraceLocation);
|
||||
}
|
||||
|
||||
setOriginalNode(block, node.body);
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a statement to capture the `this` of a function declaration if it is needed.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A node.
|
||||
*/
|
||||
export function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node, enableSubstitutionsForCapturedThis: () => void): void {
|
||||
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
|
||||
captureThisForNode(statements, node, createThis(), enableSubstitutionsForCapturedThis);
|
||||
}
|
||||
}
|
||||
|
||||
export function captureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined, enableSubstitutionsForCapturedThis?: () => void, originalStatement?: Statement): void {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
const captureThisStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_this",
|
||||
/*type*/ undefined,
|
||||
initializer
|
||||
)
|
||||
]),
|
||||
originalStatement
|
||||
);
|
||||
|
||||
setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
|
||||
setSourceMapRange(captureThisStatement, node);
|
||||
statements.push(captureThisStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether we need to add default value assignments for a
|
||||
* function-like node.
|
||||
*
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function shouldAddDefaultValueAssignments(node: FunctionLikeDeclaration): boolean {
|
||||
return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node if it contains parameters with
|
||||
* binding patterns or initializers.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
export function addDefaultValueAssignmentsIfNeeded(statements: Statement[],
|
||||
node: FunctionLikeDeclaration,
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
convertObjectRest: boolean): void {
|
||||
if (!shouldAddDefaultValueAssignments(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const parameter of node.parameters) {
|
||||
const { name, initializer, dotDotDotToken } = parameter;
|
||||
|
||||
// A rest parameter cannot have a binding pattern or an initializer,
|
||||
// so let's just ignore it.
|
||||
if (dotDotDotToken) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isBindingPattern(name)) {
|
||||
addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer, visitor, convertObjectRest);
|
||||
}
|
||||
else if (initializer) {
|
||||
addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node for parameters with binding patterns
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param parameter The parameter for the function.
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForBindingPattern(statements: Statement[],
|
||||
parameter: ParameterDeclaration,
|
||||
name: BindingPattern, initializer: Expression,
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
convertObjectRest: boolean): void {
|
||||
const temp = getGeneratedNameForNode(parameter);
|
||||
|
||||
// In cases where a binding pattern is simply '[]' or '{}',
|
||||
// we usually don't want to emit a var declaration; however, in the presence
|
||||
// of an initializer, we must emit that expression to preserve side effects.
|
||||
if (name.elements.length > 0) {
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
flattenParameterDestructuring(parameter, temp, visitor, convertObjectRest)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (initializer) {
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
temp,
|
||||
visitNode(initializer, visitor, isExpression)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node for parameters with initializers.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param parameter The parameter for the function.
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForInitializer(statements: Statement[],
|
||||
parameter: ParameterDeclaration,
|
||||
name: Identifier,
|
||||
initializer: Expression,
|
||||
visitor: (node: Node) => VisitResult<Node>): void {
|
||||
initializer = visitNode(initializer, visitor, isExpression);
|
||||
const statement = createIf(
|
||||
createStrictEquality(
|
||||
getSynthesizedClone(name),
|
||||
createVoidZero()
|
||||
),
|
||||
setEmitFlags(
|
||||
createBlock([
|
||||
createStatement(
|
||||
createAssignment(
|
||||
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
|
||||
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)),
|
||||
/*location*/ parameter
|
||||
)
|
||||
)
|
||||
], /*location*/ parameter),
|
||||
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps
|
||||
),
|
||||
/*elseStatement*/ undefined,
|
||||
/*location*/ parameter
|
||||
);
|
||||
statement.startsOnNewLine = true;
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether we need to add statements to handle a rest parameter.
|
||||
*
|
||||
* @param node A ParameterDeclaration node.
|
||||
* @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is
|
||||
* part of a constructor declaration with a
|
||||
* synthesized call to `super`
|
||||
*/
|
||||
function shouldAddRestParameter(node: ParameterDeclaration, inConstructorWithSynthesizedSuper: boolean) {
|
||||
return node && node.dotDotDotToken && node.name.kind === SyntaxKind.Identifier && !inConstructorWithSynthesizedSuper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node if it contains a rest parameter.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A function-like node.
|
||||
* @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is
|
||||
* part of a constructor declaration with a
|
||||
* synthesized call to `super`
|
||||
*/
|
||||
export function addRestParameterIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, inConstructorWithSynthesizedSuper: boolean): void {
|
||||
const parameter = lastOrUndefined(node.parameters);
|
||||
if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// `declarationName` is the name of the local declaration for the parameter.
|
||||
const declarationName = getMutableClone(<Identifier>parameter.name);
|
||||
setEmitFlags(declarationName, EmitFlags.NoSourceMap);
|
||||
|
||||
// `expressionName` is the name of the parameter used in expressions.
|
||||
const expressionName = getSynthesizedClone(<Identifier>parameter.name);
|
||||
const restIndex = node.parameters.length - 1;
|
||||
const temp = createLoopVariable();
|
||||
|
||||
// var param = [];
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
declarationName,
|
||||
/*type*/ undefined,
|
||||
createArrayLiteral([])
|
||||
)
|
||||
]),
|
||||
/*location*/ parameter
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
|
||||
// for (var _i = restIndex; _i < arguments.length; _i++) {
|
||||
// param[_i - restIndex] = arguments[_i];
|
||||
// }
|
||||
const forStatement = createFor(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex))
|
||||
], /*location*/ parameter),
|
||||
createLessThan(
|
||||
temp,
|
||||
createPropertyAccess(createIdentifier("arguments"), "length"),
|
||||
/*location*/ parameter
|
||||
),
|
||||
createPostfixIncrement(temp, /*location*/ parameter),
|
||||
createBlock([
|
||||
startOnNewLine(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
expressionName,
|
||||
createSubtract(temp, createLiteral(restIndex))
|
||||
),
|
||||
createElementAccess(createIdentifier("arguments"), temp)
|
||||
),
|
||||
/*location*/ parameter
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
setEmitFlags(forStatement, EmitFlags.CustomPrologue);
|
||||
startOnNewLine(forStatement);
|
||||
statements.push(forStatement);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export function convertForOf(node: ForOfStatement, convertedLoopBodyStatements: Statement[],
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
enableSubstitutionsForBlockScopedBindings: () => void,
|
||||
context: TransformationContext,
|
||||
convertObjectRest?: boolean): ForStatement | ForOfStatement {
|
||||
// The following ES6 code:
|
||||
//
|
||||
// for (let v of expr) { }
|
||||
//
|
||||
// should be emitted as
|
||||
//
|
||||
// for (var _i = 0, _a = expr; _i < _a.length; _i++) {
|
||||
// var v = _a[_i];
|
||||
// }
|
||||
//
|
||||
// where _a and _i are temps emitted to capture the RHS and the counter,
|
||||
// respectively.
|
||||
// When the left hand side is an expression instead of a let declaration,
|
||||
// the "let v" is not emitted.
|
||||
// When the left hand side is a let/const, the v is renamed if there is
|
||||
// another v in scope.
|
||||
// Note that all assignments to the LHS are emitted in the body, including
|
||||
// all destructuring.
|
||||
// Note also that because an extra statement is needed to assign to the LHS,
|
||||
// for-of bodies are always emitted as blocks.
|
||||
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
const initializer = node.initializer;
|
||||
const statements: Statement[] = [];
|
||||
|
||||
// In the case where the user wrote an identifier as the RHS, like this:
|
||||
//
|
||||
// for (let v of arr) { }
|
||||
//
|
||||
// we don't want to emit a temporary variable for the RHS, just use it directly.
|
||||
const counter = convertObjectRest ? undefined : createLoopVariable();
|
||||
const rhsReference = expression.kind === SyntaxKind.Identifier
|
||||
? createUniqueName((<Identifier>expression).text)
|
||||
: createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const elementAccess = convertObjectRest ? rhsReference : createElementAccess(rhsReference, counter);
|
||||
|
||||
// Initialize LHS
|
||||
// var v = _a[_i];
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
if (initializer.flags & NodeFlags.BlockScoped) {
|
||||
enableSubstitutionsForBlockScopedBindings();
|
||||
}
|
||||
|
||||
const firstOriginalDeclaration = firstOrUndefined(initializer.declarations);
|
||||
if (firstOriginalDeclaration && isBindingPattern(firstOriginalDeclaration.name)) {
|
||||
// This works whether the declaration is a var, let, or const.
|
||||
// It will use rhsIterationValue _a[_i] as the initializer.
|
||||
const declarations = flattenVariableDestructuring(
|
||||
firstOriginalDeclaration,
|
||||
elementAccess,
|
||||
visitor,
|
||||
/*recordTempVariable*/ undefined,
|
||||
convertObjectRest
|
||||
);
|
||||
|
||||
const declarationList = createVariableDeclarationList(declarations, /*location*/ initializer);
|
||||
setOriginalNode(declarationList, initializer);
|
||||
|
||||
// Adjust the source map range for the first declaration to align with the old
|
||||
// emitter.
|
||||
const firstDeclaration = declarations[0];
|
||||
const lastDeclaration = lastOrUndefined(declarations);
|
||||
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
|
||||
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
declarationList
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// The following call does not include the initializer, so we have
|
||||
// to emit it separately.
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
setOriginalNode(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
|
||||
/*type*/ undefined,
|
||||
createElementAccess(rhsReference, counter)
|
||||
)
|
||||
], /*location*/ moveRangePos(initializer, -1)),
|
||||
initializer
|
||||
),
|
||||
/*location*/ moveRangeEnd(initializer, -1)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Initializer is an expression. Emit the expression in the body, so that it's
|
||||
// evaluated on every iteration.
|
||||
const assignment = createAssignment(initializer, elementAccess);
|
||||
if (isDestructuringAssignment(assignment)) {
|
||||
// This is a destructuring pattern, so we flatten the destructuring instead.
|
||||
statements.push(
|
||||
createStatement(
|
||||
flattenDestructuringAssignment(
|
||||
context,
|
||||
assignment,
|
||||
/*needsValue*/ false,
|
||||
context.hoistVariableDeclaration,
|
||||
visitor,
|
||||
convertObjectRest
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// Currently there is not way to check that assignment is binary expression of destructing assignment
|
||||
// so we have to cast never type to binaryExpression
|
||||
(<BinaryExpression>assignment).end = initializer.end;
|
||||
statements.push(createStatement(assignment, /*location*/ moveRangeEnd(initializer, -1)));
|
||||
}
|
||||
}
|
||||
|
||||
let bodyLocation: TextRange;
|
||||
let statementsLocation: TextRange;
|
||||
if (convertedLoopBodyStatements) {
|
||||
addRange(statements, convertedLoopBodyStatements);
|
||||
}
|
||||
else {
|
||||
const statement = visitNode(node.statement, visitor, isStatement);
|
||||
if (isBlock(statement)) {
|
||||
addRange(statements, statement.statements);
|
||||
bodyLocation = statement;
|
||||
statementsLocation = statement.statements;
|
||||
}
|
||||
else {
|
||||
statements.push(statement);
|
||||
}
|
||||
}
|
||||
|
||||
// The old emitter does not emit source maps for the expression
|
||||
setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression));
|
||||
|
||||
// The old emitter does not emit source maps for the block.
|
||||
// We add the location to preserve comments.
|
||||
const body = createBlock(
|
||||
createNodeArray(statements, /*location*/ statementsLocation),
|
||||
/*location*/ bodyLocation
|
||||
);
|
||||
|
||||
setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps);
|
||||
|
||||
let forStatement: ForStatement | ForOfStatement;
|
||||
if (convertObjectRest) {
|
||||
forStatement = createForOf(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(rhsReference, /*type*/ undefined, /*initializer*/ undefined, /*location*/ node.expression)
|
||||
], /*location*/ node.expression),
|
||||
node.expression,
|
||||
body,
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
else {
|
||||
forStatement = createFor(
|
||||
setEmitFlags(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)),
|
||||
createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression)
|
||||
], /*location*/ node.expression),
|
||||
EmitFlags.NoHoisting
|
||||
),
|
||||
createLessThan(
|
||||
counter,
|
||||
createPropertyAccess(rhsReference, "length"),
|
||||
/*location*/ node.expression
|
||||
),
|
||||
createPostfixIncrement(counter, /*location*/ node.expression),
|
||||
body,
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
|
||||
// Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter.
|
||||
setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps);
|
||||
return forStatement;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1272,8 +1272,10 @@ namespace ts {
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.RestProperties:
|
||||
return isLiteralPropertyName();
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
// If we see { } then only consume it as an expression if it is followed by , or {
|
||||
// That way we won't consume the body of a class in its heritage clause.
|
||||
@ -1400,6 +1402,7 @@ namespace ts {
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
return token() === SyntaxKind.CloseBracketToken;
|
||||
case ParsingContext.Parameters:
|
||||
case ParsingContext.RestProperties:
|
||||
// Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
|
||||
return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
|
||||
case ParsingContext.TypeArguments:
|
||||
@ -1585,6 +1588,9 @@ namespace ts {
|
||||
case ParsingContext.Parameters:
|
||||
return isReusableParameter(node);
|
||||
|
||||
case ParsingContext.RestProperties:
|
||||
return false;
|
||||
|
||||
// Any other lists we do not care about reusing nodes in. But feel free to add if
|
||||
// you can do so safely. Danger areas involve nodes that may involve speculative
|
||||
// parsing. If speculative parsing is involved with the node, then the range the
|
||||
@ -1782,6 +1788,7 @@ namespace ts {
|
||||
case ParsingContext.BlockStatements: return Diagnostics.Declaration_or_statement_expected;
|
||||
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
|
||||
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
|
||||
case ParsingContext.RestProperties: // fallthrough
|
||||
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
|
||||
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
|
||||
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
|
||||
@ -4873,6 +4880,7 @@ namespace ts {
|
||||
|
||||
function parseObjectBindingElement(): BindingElement {
|
||||
const node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
const tokenIsIdentifier = isIdentifier();
|
||||
const propertyName = parsePropertyName();
|
||||
if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
|
||||
@ -5817,6 +5825,7 @@ namespace ts {
|
||||
JsxChildren, // Things between opening and closing JSX tags
|
||||
ArrayLiteralMembers, // Members in array literal
|
||||
Parameters, // Parameters in parameter list
|
||||
RestProperties, // Property names in a rest type list
|
||||
TypeParameters, // Type parameters in type parameter list
|
||||
TypeArguments, // Type arguments in type argument list
|
||||
TupleElementTypes, // Element types in tuple element type list
|
||||
|
||||
@ -17,7 +17,8 @@ namespace ts {
|
||||
node: BinaryExpression,
|
||||
needsValue: boolean,
|
||||
recordTempVariable: (node: Identifier) => void,
|
||||
visitor?: (node: Node) => VisitResult<Node>): Expression {
|
||||
visitor?: (node: Node) => VisitResult<Node>,
|
||||
transformRest?: boolean): Expression {
|
||||
|
||||
if (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
const right = node.right;
|
||||
@ -51,7 +52,7 @@ namespace ts {
|
||||
location = value;
|
||||
}
|
||||
|
||||
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, recordTempVariable, emitRestAssignment, transformRest, visitor);
|
||||
|
||||
if (needsValue) {
|
||||
expressions.push(value);
|
||||
@ -61,7 +62,7 @@ namespace ts {
|
||||
aggregateTransformFlags(expression);
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
function emitAssignment(name: Identifier | ObjectLiteralExpression, value: Expression, location: TextRange) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
@ -77,6 +78,10 @@ namespace ts {
|
||||
emitAssignment(name, value, location);
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitRestAssignment(elements: ObjectLiteralElementLike[], value: Expression, location: TextRange) {
|
||||
emitAssignment(createObjectLiteral(elements), value, location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,14 +94,15 @@ namespace ts {
|
||||
export function flattenParameterDestructuring(
|
||||
node: ParameterDeclaration,
|
||||
value: Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
visitor?: (node: Node) => VisitResult<Node>,
|
||||
transformRest?: boolean) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, noop, emitRestAssignment, transformRest, visitor);
|
||||
|
||||
return declarations;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
function emitAssignment(name: Identifier | BindingPattern, value: Expression, location: TextRange) {
|
||||
const declaration = createVariableDeclaration(name, /*type*/ undefined, value, location);
|
||||
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
@ -112,6 +118,10 @@ namespace ts {
|
||||
emitAssignment(name, value, location);
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitRestAssignment(elements: BindingElement[], value: Expression, location: TextRange) {
|
||||
emitAssignment(createObjectBindingPattern(elements), value, location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,15 +135,16 @@ namespace ts {
|
||||
node: VariableDeclaration,
|
||||
value?: Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>,
|
||||
recordTempVariable?: (node: Identifier) => void) {
|
||||
recordTempVariable?: (node: Identifier) => void,
|
||||
transformRest?: boolean) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
|
||||
let pendingAssignments: Expression[];
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, recordTempVariable, emitRestAssignment, transformRest, visitor);
|
||||
|
||||
return declarations;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
function emitAssignment(name: Identifier | BindingPattern, value: Expression, location: TextRange, original: Node) {
|
||||
if (pendingAssignments) {
|
||||
pendingAssignments.push(value);
|
||||
value = inlineExpressions(pendingAssignments);
|
||||
@ -167,6 +178,10 @@ namespace ts {
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitRestAssignment(elements: BindingElement[], value: Expression, location: TextRange, original: Node) {
|
||||
emitAssignment(createObjectBindingPattern(elements), value, location, original);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,15 +201,17 @@ namespace ts {
|
||||
|
||||
const pendingAssignments: Expression[] = [];
|
||||
|
||||
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, noop, emitRestAssignment, /*transformRest*/ false, visitor);
|
||||
|
||||
const expression = inlineExpressions(pendingAssignments);
|
||||
aggregateTransformFlags(expression);
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
function emitAssignment(name: Identifier | ObjectLiteralExpression, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignmentCallback
|
||||
? createAssignmentCallback(name, value, location)
|
||||
? createAssignmentCallback(name.kind === SyntaxKind.Identifier ? name : emitTempVariableAssignment(name, location),
|
||||
value,
|
||||
location)
|
||||
: createAssignment(name, value, location);
|
||||
|
||||
emitPendingAssignment(expression, original);
|
||||
@ -206,6 +223,10 @@ namespace ts {
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitRestAssignment(elements: ObjectLiteralElementLike[], value: Expression, location: TextRange, original: Node) {
|
||||
emitAssignment(createObjectLiteral(elements), value, location, original);
|
||||
}
|
||||
|
||||
function emitPendingAssignment(expression: Expression, original: Node) {
|
||||
expression.original = original;
|
||||
|
||||
@ -223,6 +244,9 @@ namespace ts {
|
||||
location: TextRange,
|
||||
emitAssignment: (name: Identifier, value: Expression, location: TextRange, original: Node) => void,
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
|
||||
recordTempVariable: (node: Identifier) => void,
|
||||
emitRestAssignment: (elements: (ObjectLiteralElementLike[] | BindingElement[]), value: Expression, location: TextRange, original: Node) => void,
|
||||
transformRest: boolean,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
if (value && visitor) {
|
||||
value = visitNode(value, visitor, isExpression);
|
||||
@ -284,23 +308,91 @@ namespace ts {
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
}
|
||||
|
||||
for (const p of properties) {
|
||||
let bindingElements: ObjectLiteralElementLike[] = [];
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
const p = properties[i];
|
||||
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
const propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
|
||||
const target = p.kind === SyntaxKind.ShorthandPropertyAssignment ? <ShorthandPropertyAssignment>p : (<PropertyAssignment>p).initializer || propName;
|
||||
// Assignment for target = value.propName should highligh whole property, hence use p as source map node
|
||||
emitDestructuringAssignment(target, createDestructuringPropertyAccess(value, propName), p);
|
||||
if (!transformRest ||
|
||||
p.transformFlags & TransformFlags.ContainsSpreadExpression ||
|
||||
(p.kind === SyntaxKind.PropertyAssignment && p.initializer.transformFlags & TransformFlags.ContainsSpreadExpression)) {
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, location, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
const propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
|
||||
const bindingTarget = p.kind === SyntaxKind.ShorthandPropertyAssignment ? <ShorthandPropertyAssignment>p : (<PropertyAssignment>p).initializer || propName;
|
||||
// Assignment for bindingTarget = value.propName should highlight whole property, hence use p as source map node
|
||||
emitDestructuringAssignment(bindingTarget, createDestructuringPropertyAccess(value, propName), p);
|
||||
}
|
||||
else {
|
||||
bindingElements.push(p);
|
||||
}
|
||||
}
|
||||
else if (i === properties.length - 1 && p.kind === SyntaxKind.SpreadAssignment) {
|
||||
Debug.assert((p as SpreadAssignment).expression.kind === SyntaxKind.Identifier);
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, location, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
const propName = (p as SpreadAssignment).expression as Identifier;
|
||||
const restCall = createRestCall(value, target.properties, p => p.name, target);
|
||||
emitDestructuringAssignment(propName, restCall, p);
|
||||
}
|
||||
}
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, location, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
}
|
||||
|
||||
function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, location: TextRange) {
|
||||
if (transformRest) {
|
||||
emitESNextArrayLiteralAssignment(target, value, location);
|
||||
}
|
||||
else {
|
||||
emitES2015ArrayLiteralAssignment(target, value, location);
|
||||
}
|
||||
}
|
||||
|
||||
function emitESNextArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, location: TextRange) {
|
||||
const elements = target.elements;
|
||||
const numElements = elements.length;
|
||||
if (numElements !== 1) {
|
||||
// For anything but a single element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once.
|
||||
// When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment
|
||||
// When doing so we want to highlight the passed-in source map node since thats the one needing this temp assignment
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
}
|
||||
|
||||
const expressions: Expression[] = [];
|
||||
const spreadContainingExpressions: [Expression, Identifier][] = [];
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const e = elements[i];
|
||||
if (e.kind === SyntaxKind.OmittedExpression) {
|
||||
continue;
|
||||
}
|
||||
if (e.transformFlags & TransformFlags.ContainsSpreadExpression && i < numElements - 1) {
|
||||
const tmp = createTempVariable(recordTempVariable);
|
||||
spreadContainingExpressions.push([e, tmp]);
|
||||
expressions.push(tmp);
|
||||
}
|
||||
else {
|
||||
expressions.push(e);
|
||||
}
|
||||
}
|
||||
emitAssignment(updateArrayLiteral(target, expressions) as any as Identifier, value, undefined, undefined);
|
||||
for (const [e, tmp] of spreadContainingExpressions) {
|
||||
emitDestructuringAssignment(e, tmp, e);
|
||||
}
|
||||
}
|
||||
|
||||
function emitES2015ArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, location: TextRange) {
|
||||
const elements = target.elements;
|
||||
const numElements = elements.length;
|
||||
if (numElements !== 1) {
|
||||
// For anything but a single element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once.
|
||||
// When doing so we want to highlight the passed-in source map node since thats the one needing this temp assignment
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
}
|
||||
|
||||
@ -318,10 +410,31 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
|
||||
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`*/
|
||||
function createRestCall<T extends Node>(value: Expression, elements: T[], getPropertyName: (element: T) => PropertyName, location: TextRange): Expression {
|
||||
const propertyNames: LiteralExpression[] = [];
|
||||
for (let i = 0; i < elements.length - 1; i++) {
|
||||
if (isOmittedExpression(elements[i])) {
|
||||
continue;
|
||||
}
|
||||
const str = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
|
||||
str.pos = location.pos;
|
||||
str.end = location.end;
|
||||
str.text = getTextOfPropertyName(getPropertyName(elements[i]));
|
||||
propertyNames.push(str);
|
||||
}
|
||||
const args = createSynthesizedNodeArray([value, createArrayLiteral(propertyNames, location)]);
|
||||
return createCall(createIdentifier("__rest"), undefined, args);
|
||||
}
|
||||
|
||||
function emitBindingElement(target: VariableDeclaration | ParameterDeclaration | BindingElement, value: Expression) {
|
||||
// Any temporary assignments needed to emit target = value should point to target
|
||||
const initializer = visitor ? visitNode(target.initializer, visitor, isExpression) : target.initializer;
|
||||
if (initializer) {
|
||||
if (transformRest) {
|
||||
value = value || initializer;
|
||||
}
|
||||
else if (initializer) {
|
||||
// Combine value and initializer
|
||||
value = value ? createDefaultValueCheck(value, initializer, target) : initializer;
|
||||
}
|
||||
@ -331,9 +444,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
const name = target.name;
|
||||
if (isBindingPattern(name)) {
|
||||
const elements = name.elements;
|
||||
const numElements = elements.length;
|
||||
if (!isBindingPattern(name)) {
|
||||
emitAssignment(name, value, target, target);
|
||||
}
|
||||
else {
|
||||
const numElements = name.elements.length;
|
||||
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
|
||||
@ -341,29 +456,104 @@ namespace ts {
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target, emitTempVariableAssignment);
|
||||
}
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
else if (name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
const propName = element.propertyName || <Identifier>element.name;
|
||||
emitBindingElement(element, createDestructuringPropertyAccess(value, propName));
|
||||
}
|
||||
else {
|
||||
if (!element.dotDotDotToken) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccess(value, i));
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
emitBindingElement(element, createArraySlice(value, i));
|
||||
}
|
||||
}
|
||||
if (name.kind === SyntaxKind.ArrayBindingPattern) {
|
||||
emitArrayBindingElement(name as ArrayBindingPattern, value);
|
||||
}
|
||||
else {
|
||||
emitObjectBindingElement(target, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitArrayBindingElement(name: ArrayBindingPattern, value: Expression) {
|
||||
if (transformRest) {
|
||||
emitESNextArrayBindingElement(name, value);
|
||||
}
|
||||
else {
|
||||
emitAssignment(name, value, target, target);
|
||||
emitES2015ArrayBindingElement(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
function emitES2015ArrayBindingElement(name: ArrayBindingPattern, value: Expression) {
|
||||
const elements = name.elements;
|
||||
const numElements = elements.length;
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
if (!element.dotDotDotToken) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccess(value, i));
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
emitBindingElement(element, createArraySlice(value, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitESNextArrayBindingElement(name: ArrayBindingPattern, value: Expression) {
|
||||
const elements = name.elements;
|
||||
const numElements = elements.length;
|
||||
const bindingElements: BindingElement[] = [];
|
||||
const spreadContainingElements: BindingElement[] = [];
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
if (element.transformFlags & TransformFlags.ContainsSpreadExpression && i < numElements - 1) {
|
||||
spreadContainingElements.push(element);
|
||||
bindingElements.push(createBindingElement(undefined, undefined, getGeneratedNameForNode(element), undefined, value));
|
||||
}
|
||||
else {
|
||||
bindingElements.push(element);
|
||||
}
|
||||
}
|
||||
emitAssignment(updateArrayBindingPattern(name, bindingElements) as any as Identifier, value, undefined, undefined);
|
||||
for (const element of spreadContainingElements) {
|
||||
emitBindingElement(element, getGeneratedNameForNode(element));
|
||||
}
|
||||
}
|
||||
|
||||
function emitObjectBindingElement(target: VariableDeclaration | ParameterDeclaration | BindingElement, value: Expression) {
|
||||
const name = target.name as BindingPattern;
|
||||
const elements = name.elements;
|
||||
const numElements = elements.length;
|
||||
let bindingElements: BindingElement[] = [];
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
if (i === numElements - 1 && element.dotDotDotToken) {
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, target, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
const restCall = createRestCall(value,
|
||||
name.elements,
|
||||
element => (element as BindingElement).propertyName || <Identifier>(element as BindingElement).name,
|
||||
name);
|
||||
emitBindingElement(element, restCall);
|
||||
}
|
||||
else if (transformRest && !(element.transformFlags & TransformFlags.ContainsSpreadExpression)) {
|
||||
// do not emit until we have a complete bundle of ES2015 syntax
|
||||
bindingElements.push(element);
|
||||
}
|
||||
else {
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, target, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
const propName = element.propertyName || <Identifier>element.name;
|
||||
emitBindingElement(element, createDestructuringPropertyAccess(value, propName));
|
||||
}
|
||||
}
|
||||
if (bindingElements.length) {
|
||||
emitRestAssignment(bindingElements, value, target, target);
|
||||
bindingElements = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -861,7 +861,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (constructor) {
|
||||
addDefaultValueAssignmentsIfNeeded(statements, constructor);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, constructor, visitor, /*convertObjectRest*/ false);
|
||||
addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper);
|
||||
Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!");
|
||||
|
||||
@ -954,7 +954,7 @@ namespace ts {
|
||||
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
|
||||
if (!hasExtendsClause) {
|
||||
if (ctor) {
|
||||
addCaptureThisForNodeIfNeeded(statements, ctor);
|
||||
addCaptureThisForNodeIfNeeded(statements, ctor, enableSubstitutionsForCapturedThis);
|
||||
}
|
||||
return SuperCaptureResult.NoReplacement;
|
||||
}
|
||||
@ -1016,7 +1016,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Perform the capture.
|
||||
captureThisForNode(statements, ctor, superCallExpression, firstStatement);
|
||||
captureThisForNode(statements, ctor, superCallExpression, enableSubstitutionsForCapturedThis, firstStatement);
|
||||
|
||||
// If we're actually replacing the original statement, we need to signal this to the caller.
|
||||
if (superCallExpression) {
|
||||
@ -1085,242 +1085,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether we need to add default value assignments for a
|
||||
* function-like node.
|
||||
*
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function shouldAddDefaultValueAssignments(node: FunctionLikeDeclaration): boolean {
|
||||
return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node if it contains parameters with
|
||||
* binding patterns or initializers.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function addDefaultValueAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): void {
|
||||
if (!shouldAddDefaultValueAssignments(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const parameter of node.parameters) {
|
||||
const { name, initializer, dotDotDotToken } = parameter;
|
||||
|
||||
// A rest parameter cannot have a binding pattern or an initializer,
|
||||
// so let's just ignore it.
|
||||
if (dotDotDotToken) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isBindingPattern(name)) {
|
||||
addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer);
|
||||
}
|
||||
else if (initializer) {
|
||||
addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node for parameters with binding patterns
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param parameter The parameter for the function.
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression): void {
|
||||
const temp = getGeneratedNameForNode(parameter);
|
||||
|
||||
// In cases where a binding pattern is simply '[]' or '{}',
|
||||
// we usually don't want to emit a var declaration; however, in the presence
|
||||
// of an initializer, we must emit that expression to preserve side effects.
|
||||
if (name.elements.length > 0) {
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
flattenParameterDestructuring(parameter, temp, visitor)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (initializer) {
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
temp,
|
||||
visitNode(initializer, visitor, isExpression)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node for parameters with initializers.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param parameter The parameter for the function.
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForInitializer(statements: Statement[], parameter: ParameterDeclaration, name: Identifier, initializer: Expression): void {
|
||||
initializer = visitNode(initializer, visitor, isExpression);
|
||||
const statement = createIf(
|
||||
createStrictEquality(
|
||||
getSynthesizedClone(name),
|
||||
createVoidZero()
|
||||
),
|
||||
setEmitFlags(
|
||||
createBlock([
|
||||
createStatement(
|
||||
createAssignment(
|
||||
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
|
||||
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)),
|
||||
/*location*/ parameter
|
||||
)
|
||||
)
|
||||
], /*location*/ parameter),
|
||||
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps
|
||||
),
|
||||
/*elseStatement*/ undefined,
|
||||
/*location*/ parameter
|
||||
);
|
||||
statement.startsOnNewLine = true;
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether we need to add statements to handle a rest parameter.
|
||||
*
|
||||
* @param node A ParameterDeclaration node.
|
||||
* @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is
|
||||
* part of a constructor declaration with a
|
||||
* synthesized call to `super`
|
||||
*/
|
||||
function shouldAddRestParameter(node: ParameterDeclaration, inConstructorWithSynthesizedSuper: boolean) {
|
||||
return node && node.dotDotDotToken && node.name.kind === SyntaxKind.Identifier && !inConstructorWithSynthesizedSuper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the body of a function-like node if it contains a rest parameter.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A function-like node.
|
||||
* @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is
|
||||
* part of a constructor declaration with a
|
||||
* synthesized call to `super`
|
||||
*/
|
||||
function addRestParameterIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, inConstructorWithSynthesizedSuper: boolean): void {
|
||||
const parameter = lastOrUndefined(node.parameters);
|
||||
if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// `declarationName` is the name of the local declaration for the parameter.
|
||||
const declarationName = getMutableClone(<Identifier>parameter.name);
|
||||
setEmitFlags(declarationName, EmitFlags.NoSourceMap);
|
||||
|
||||
// `expressionName` is the name of the parameter used in expressions.
|
||||
const expressionName = getSynthesizedClone(<Identifier>parameter.name);
|
||||
const restIndex = node.parameters.length - 1;
|
||||
const temp = createLoopVariable();
|
||||
|
||||
// var param = [];
|
||||
statements.push(
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
declarationName,
|
||||
/*type*/ undefined,
|
||||
createArrayLiteral([])
|
||||
)
|
||||
]),
|
||||
/*location*/ parameter
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
|
||||
// for (var _i = restIndex; _i < arguments.length; _i++) {
|
||||
// param[_i - restIndex] = arguments[_i];
|
||||
// }
|
||||
const forStatement = createFor(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex))
|
||||
], /*location*/ parameter),
|
||||
createLessThan(
|
||||
temp,
|
||||
createPropertyAccess(createIdentifier("arguments"), "length"),
|
||||
/*location*/ parameter
|
||||
),
|
||||
createPostfixIncrement(temp, /*location*/ parameter),
|
||||
createBlock([
|
||||
startOnNewLine(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
expressionName,
|
||||
createSubtract(temp, createLiteral(restIndex))
|
||||
),
|
||||
createElementAccess(createIdentifier("arguments"), temp)
|
||||
),
|
||||
/*location*/ parameter
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
setEmitFlags(forStatement, EmitFlags.CustomPrologue);
|
||||
startOnNewLine(forStatement);
|
||||
statements.push(forStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a statement to capture the `this` of a function declaration if it is needed.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A node.
|
||||
*/
|
||||
function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): void {
|
||||
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
|
||||
captureThisForNode(statements, node, createThis());
|
||||
}
|
||||
}
|
||||
|
||||
function captureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined, originalStatement?: Statement): void {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
const captureThisStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_this",
|
||||
/*type*/ undefined,
|
||||
initializer
|
||||
)
|
||||
]),
|
||||
originalStatement
|
||||
);
|
||||
|
||||
setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
|
||||
setSourceMapRange(captureThisStatement, node);
|
||||
statements.push(captureThisStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds statements to the class body function for a class to define the members of the
|
||||
* class.
|
||||
@ -1518,7 +1282,7 @@ namespace ts {
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node),
|
||||
transformFunctionBody(node, visitor, currentSourceFile, context, enableSubstitutionsForCapturedThis),
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node);
|
||||
@ -1545,7 +1309,7 @@ namespace ts {
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
saveStateAndInvoke(node, transformFunctionBody),
|
||||
saveStateAndInvoke(node, node => transformFunctionBody(node, visitor, currentSourceFile, context, enableSubstitutionsForCapturedThis)),
|
||||
location
|
||||
),
|
||||
/*original*/ node
|
||||
@ -1555,96 +1319,6 @@ namespace ts {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the body of a function-like node.
|
||||
*
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function transformFunctionBody(node: FunctionLikeDeclaration) {
|
||||
let multiLine = false; // indicates whether the block *must* be emitted as multiple lines
|
||||
let singleLine = false; // indicates whether the block *may* be emitted as a single line
|
||||
let statementsLocation: TextRange;
|
||||
let closeBraceLocation: TextRange;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body;
|
||||
let statementOffset: number;
|
||||
|
||||
startLexicalEnvironment();
|
||||
if (isBlock(body)) {
|
||||
// ensureUseStrict is false because no new prologue-directive should be added.
|
||||
// addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
}
|
||||
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, node);
|
||||
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
|
||||
// If we added any generated statements, this must be a multi-line block.
|
||||
if (!multiLine && statements.length > 0) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
if (isBlock(body)) {
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
|
||||
|
||||
// If the original body was a multi-line block, this must be a multi-line block.
|
||||
if (!multiLine && body.multiLine) {
|
||||
multiLine = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assert(node.kind === SyntaxKind.ArrowFunction);
|
||||
|
||||
// To align with the old emitter, we use a synthetic end position on the location
|
||||
// for the statement list we synthesize when we down-level an arrow function with
|
||||
// an expression function body. This prevents both comments and source maps from
|
||||
// being emitted for the end position only.
|
||||
statementsLocation = moveRangeEnd(body, -1);
|
||||
|
||||
const equalsGreaterThanToken = (<ArrowFunction>node).equalsGreaterThanToken;
|
||||
if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) {
|
||||
if (rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) {
|
||||
singleLine = true;
|
||||
}
|
||||
else {
|
||||
multiLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
const expression = visitNode(body, visitor, isExpression);
|
||||
const returnStatement = createReturn(expression, /*location*/ body);
|
||||
setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments);
|
||||
statements.push(returnStatement);
|
||||
|
||||
// To align with the source map emit for the old emitter, we set a custom
|
||||
// source map location for the close brace.
|
||||
closeBraceLocation = body;
|
||||
}
|
||||
|
||||
const lexicalEnvironment = endLexicalEnvironment();
|
||||
addRange(statements, lexicalEnvironment);
|
||||
|
||||
// If we added any final generated statements, this must be a multi-line block
|
||||
if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine);
|
||||
if (!multiLine && singleLine) {
|
||||
setEmitFlags(block, EmitFlags.SingleLine);
|
||||
}
|
||||
|
||||
if (closeBraceLocation) {
|
||||
setTokenSourceMapRange(block, SyntaxKind.CloseBraceToken, closeBraceLocation);
|
||||
}
|
||||
|
||||
setOriginalNode(block, node.body);
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an ExpressionStatement that contains a destructuring assignment.
|
||||
*
|
||||
@ -1926,171 +1600,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function convertForOfToFor(node: ForOfStatement, convertedLoopBodyStatements: Statement[]): ForStatement {
|
||||
// The following ES6 code:
|
||||
//
|
||||
// for (let v of expr) { }
|
||||
//
|
||||
// should be emitted as
|
||||
//
|
||||
// for (var _i = 0, _a = expr; _i < _a.length; _i++) {
|
||||
// var v = _a[_i];
|
||||
// }
|
||||
//
|
||||
// where _a and _i are temps emitted to capture the RHS and the counter,
|
||||
// respectively.
|
||||
// When the left hand side is an expression instead of a let declaration,
|
||||
// the "let v" is not emitted.
|
||||
// When the left hand side is a let/const, the v is renamed if there is
|
||||
// another v in scope.
|
||||
// Note that all assignments to the LHS are emitted in the body, including
|
||||
// all destructuring.
|
||||
// Note also that because an extra statement is needed to assign to the LHS,
|
||||
// for-of bodies are always emitted as blocks.
|
||||
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
const initializer = node.initializer;
|
||||
const statements: Statement[] = [];
|
||||
|
||||
// In the case where the user wrote an identifier as the RHS, like this:
|
||||
//
|
||||
// for (let v of arr) { }
|
||||
//
|
||||
// we don't want to emit a temporary variable for the RHS, just use it directly.
|
||||
const counter = createLoopVariable();
|
||||
const rhsReference = expression.kind === SyntaxKind.Identifier
|
||||
? createUniqueName((<Identifier>expression).text)
|
||||
: createTempVariable(/*recordTempVariable*/ undefined);
|
||||
|
||||
// Initialize LHS
|
||||
// var v = _a[_i];
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
if (initializer.flags & NodeFlags.BlockScoped) {
|
||||
enableSubstitutionsForBlockScopedBindings();
|
||||
}
|
||||
|
||||
const firstOriginalDeclaration = firstOrUndefined(initializer.declarations);
|
||||
if (firstOriginalDeclaration && isBindingPattern(firstOriginalDeclaration.name)) {
|
||||
// This works whether the declaration is a var, let, or const.
|
||||
// It will use rhsIterationValue _a[_i] as the initializer.
|
||||
const declarations = flattenVariableDestructuring(
|
||||
firstOriginalDeclaration,
|
||||
createElementAccess(rhsReference, counter),
|
||||
visitor
|
||||
);
|
||||
|
||||
const declarationList = createVariableDeclarationList(declarations, /*location*/ initializer);
|
||||
setOriginalNode(declarationList, initializer);
|
||||
|
||||
// Adjust the source map range for the first declaration to align with the old
|
||||
// emitter.
|
||||
const firstDeclaration = declarations[0];
|
||||
const lastDeclaration = lastOrUndefined(declarations);
|
||||
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
|
||||
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
declarationList
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// The following call does not include the initializer, so we have
|
||||
// to emit it separately.
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
setOriginalNode(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
|
||||
/*type*/ undefined,
|
||||
createElementAccess(rhsReference, counter)
|
||||
)
|
||||
], /*location*/ moveRangePos(initializer, -1)),
|
||||
initializer
|
||||
),
|
||||
/*location*/ moveRangeEnd(initializer, -1)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Initializer is an expression. Emit the expression in the body, so that it's
|
||||
// evaluated on every iteration.
|
||||
const assignment = createAssignment(initializer, createElementAccess(rhsReference, counter));
|
||||
if (isDestructuringAssignment(assignment)) {
|
||||
// This is a destructuring pattern, so we flatten the destructuring instead.
|
||||
statements.push(
|
||||
createStatement(
|
||||
flattenDestructuringAssignment(
|
||||
context,
|
||||
assignment,
|
||||
/*needsValue*/ false,
|
||||
hoistVariableDeclaration,
|
||||
visitor
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// Currently there is not way to check that assignment is binary expression of destructing assignment
|
||||
// so we have to cast never type to binaryExpression
|
||||
(<BinaryExpression>assignment).end = initializer.end;
|
||||
statements.push(createStatement(assignment, /*location*/ moveRangeEnd(initializer, -1)));
|
||||
}
|
||||
}
|
||||
|
||||
let bodyLocation: TextRange;
|
||||
let statementsLocation: TextRange;
|
||||
if (convertedLoopBodyStatements) {
|
||||
addRange(statements, convertedLoopBodyStatements);
|
||||
}
|
||||
else {
|
||||
const statement = visitNode(node.statement, visitor, isStatement);
|
||||
if (isBlock(statement)) {
|
||||
addRange(statements, statement.statements);
|
||||
bodyLocation = statement;
|
||||
statementsLocation = statement.statements;
|
||||
}
|
||||
else {
|
||||
statements.push(statement);
|
||||
}
|
||||
}
|
||||
|
||||
// The old emitter does not emit source maps for the expression
|
||||
setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression));
|
||||
|
||||
// The old emitter does not emit source maps for the block.
|
||||
// We add the location to preserve comments.
|
||||
const body = createBlock(
|
||||
createNodeArray(statements, /*location*/ statementsLocation),
|
||||
/*location*/ bodyLocation
|
||||
);
|
||||
|
||||
setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps);
|
||||
|
||||
const forStatement = createFor(
|
||||
setEmitFlags(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)),
|
||||
createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression)
|
||||
], /*location*/ node.expression),
|
||||
EmitFlags.NoHoisting
|
||||
),
|
||||
createLessThan(
|
||||
counter,
|
||||
createPropertyAccess(rhsReference, "length"),
|
||||
/*location*/ node.expression
|
||||
),
|
||||
createPostfixIncrement(counter, /*location*/ node.expression),
|
||||
body,
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
// Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter.
|
||||
setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps);
|
||||
return forStatement;
|
||||
return <ForStatement>convertForOf(node, convertedLoopBodyStatements, visitor, enableSubstitutionsForBlockScopedBindings, context, /*transformRest*/ false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3076,7 +2586,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
addRange(statements, prologue);
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
addCaptureThisForNodeIfNeeded(statements, node, enableSubstitutionsForCapturedThis);
|
||||
addRange(statements, visitNodes(createNodeArray(remaining), visitor, isStatement));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
const clone = getMutableClone(node);
|
||||
|
||||
@ -4,9 +4,14 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function transformESNext(context: TransformationContext) {
|
||||
const {
|
||||
hoistVariableDeclaration,
|
||||
} = context;
|
||||
let currentSourceFile: SourceFile;
|
||||
return transformSourceFile;
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
currentSourceFile = node;
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
@ -26,6 +31,23 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return visitBinaryExpression(node as BinaryExpression);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return visitVariableDeclaration(node as VariableDeclaration);
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return visitForOfStatement(node as ForOfStatement);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return node;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunctionDeclaration(node as FunctionDeclaration);
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return visitFunctionExpression(node as FunctionExpression);
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return visitArrowFunction(node as ArrowFunction);
|
||||
case SyntaxKind.Parameter:
|
||||
return visitParameter(node as ParameterDeclaration);
|
||||
default:
|
||||
Debug.failBadSyntaxKind(node);
|
||||
return visitEachChild(node, visitor, context);
|
||||
@ -76,5 +98,175 @@ namespace ts {
|
||||
}
|
||||
return createCall(createIdentifier("__assign"), undefined, objects);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a BinaryExpression that contains a destructuring assignment.
|
||||
*
|
||||
* @param node A BinaryExpression node.
|
||||
*/
|
||||
function visitBinaryExpression(node: BinaryExpression): Expression {
|
||||
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.AssertESNext) {
|
||||
return flattenDestructuringAssignment(context, node, /*needsDestructuringValue*/ true, hoistVariableDeclaration, visitor, /*transformRest*/ true);
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a VariableDeclaration node with a binding pattern.
|
||||
*
|
||||
* @param node A VariableDeclaration node.
|
||||
*/
|
||||
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
|
||||
// If we are here it is because the name contains a binding pattern with a rest somewhere in it.
|
||||
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.AssertESNext) {
|
||||
const result = flattenVariableDestructuring(node, /*value*/ undefined, visitor, /*recordTempVariable*/ undefined, /*transformRest*/ true);
|
||||
return result;
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a ForOfStatement and converts it into a ES2015-compatible ForOfStatement.
|
||||
*
|
||||
* @param node A ForOfStatement.
|
||||
*/
|
||||
function visitForOfStatement(node: ForOfStatement): VisitResult<Statement> {
|
||||
// The following ESNext code:
|
||||
//
|
||||
// for (let { x, y, ...rest } of expr) { }
|
||||
//
|
||||
// should be emitted as
|
||||
//
|
||||
// for (var _a of expr) {
|
||||
// let { x, y } = _a, rest = __rest(_a, ["x", "y"]);
|
||||
// }
|
||||
//
|
||||
// where _a is a temp emitted to capture the RHS.
|
||||
// When the left hand side is an expression instead of a let declaration,
|
||||
// the `let` before the `{ x, y }` is not emitted.
|
||||
// When the left hand side is a let/const, the v is renamed if there is
|
||||
// another v in scope.
|
||||
// Note that all assignments to the LHS are emitted in the body, including
|
||||
// all destructuring.
|
||||
// Note also that because an extra statement is needed to assign to the LHS,
|
||||
// for-of bodies are always emitted as blocks.
|
||||
|
||||
// for (<init> of <expression>) <statement>
|
||||
// where <init> is [let] variabledeclarationlist | expression
|
||||
const initializer = node.initializer;
|
||||
if (!isRestBindingPattern(initializer) && !isRestAssignment(initializer)) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
return convertForOf(node, undefined, visitor, noop, context, /*transformRest*/ true);
|
||||
}
|
||||
|
||||
function isRestBindingPattern(initializer: ForInitializer) {
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
const declaration = firstOrUndefined(initializer.declarations);
|
||||
return declaration && declaration.name &&
|
||||
declaration.name.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
!!(declaration.name.transformFlags & TransformFlags.ContainsSpreadExpression);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRestAssignment(initializer: ForInitializer) {
|
||||
return initializer.kind === SyntaxKind.ObjectLiteralExpression &&
|
||||
initializer.transformFlags & TransformFlags.ContainsSpreadExpression;
|
||||
}
|
||||
|
||||
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
|
||||
if (isObjectRestParameter(node)) {
|
||||
// Binding patterns are converted into a generated name and are
|
||||
// evaluated inside the function body.
|
||||
return setOriginalNode(
|
||||
createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
getGeneratedNameForNode(node),
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
node.initializer,
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
);
|
||||
}
|
||||
else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
function isObjectRestParameter(node: ParameterDeclaration) {
|
||||
return node.name &&
|
||||
node.name.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
!!(node.name.transformFlags & TransformFlags.ContainsSpreadExpression);
|
||||
}
|
||||
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): FunctionDeclaration {
|
||||
const hasRest = forEach(node.parameters, isObjectRestParameter);
|
||||
const body = hasRest ?
|
||||
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
|
||||
visitEachChild(node.body, visitor, context);
|
||||
|
||||
return setOriginalNode(
|
||||
createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
body,
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node);
|
||||
}
|
||||
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
const hasRest = forEach(node.parameters, isObjectRestParameter);
|
||||
const body = hasRest ?
|
||||
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
|
||||
visitEachChild(node.body, visitor, context);
|
||||
const func = setOriginalNode(
|
||||
createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
node.equalsGreaterThanToken,
|
||||
body,
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
);
|
||||
setEmitFlags(func, EmitFlags.CapturesThis);
|
||||
return func;
|
||||
}
|
||||
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
const hasRest = forEach(node.parameters, isObjectRestParameter);
|
||||
const body = hasRest ?
|
||||
transformFunctionBody(node, visitor, currentSourceFile, context, noop, /*convertObjectRest*/ true) as Block :
|
||||
visitEachChild(node.body, visitor, context);
|
||||
return setOriginalNode(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.asteriskToken,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
body,
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,14 +420,15 @@ namespace ts {
|
||||
HasParamDecorators = 1 << 12, // If the file has parameter decorators (initialized by binding)
|
||||
HasAsyncFunctions = 1 << 13, // If the file has async functions (initialized by binding)
|
||||
HasSpreadAttribute = 1 << 14, // If the file as JSX spread attributes (initialized by binding)
|
||||
DisallowInContext = 1 << 15, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 16, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 17, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 18, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 19, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 20, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 21, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
|
||||
HasRestAttribute = 1 << 15, // If the file has object destructure elements
|
||||
DisallowInContext = 1 << 16, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 17, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 18, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 19, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 20, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 21, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 22, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 23, // If we've computed data from children and cached it in this node
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@ -649,7 +650,7 @@ namespace ts {
|
||||
export interface BindingElement extends Declaration {
|
||||
kind: SyntaxKind.BindingElement;
|
||||
propertyName?: PropertyName; // Binding property name (in object binding pattern)
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest binding element
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern)
|
||||
name: BindingName; // Declared binding element name
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
@ -485,6 +485,22 @@ namespace ts {
|
||||
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
||||
}
|
||||
|
||||
export function getTextOfPropertyName(name: PropertyName): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return (<Identifier>name).text;
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return (<LiteralExpression>name).text;
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
|
||||
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function entityNameToString(name: EntityNameOrEntityNameExpression): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
|
||||
67
tests/baselines/reference/objectRest.js
Normal file
67
tests/baselines/reference/objectRest.js
Normal file
@ -0,0 +1,67 @@
|
||||
//// [objectRest.ts]
|
||||
let o = { a: 1, b: 'no' }
|
||||
var { ...clone } = o;
|
||||
var { a, ...justB } = o;
|
||||
var { a, b: renamed, ...empty } = o;
|
||||
var { ['b']: renamed, ...justA } = o;
|
||||
var { 'b': renamed, ...justA } = o;
|
||||
var { b: { '0': n, '1': oooo }, ...justA } = o;
|
||||
|
||||
let o2 = { c: 'terrible idea?', d: 'yes' };
|
||||
var { d: renamed, ...d } = o2;
|
||||
|
||||
let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number };
|
||||
var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest;
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
var { x: { ka, ...nested }, y: other, ...rest } = complex;
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
var { x, ...fresh } = { x: 1, y: 2 };
|
||||
({ x, ...fresh } = { x: 1, y: 2 });
|
||||
|
||||
class Removable {
|
||||
private x: number;
|
||||
protected y: number;
|
||||
set z(value: number) { }
|
||||
get both(): number { return 12 }
|
||||
set both(value: number) { }
|
||||
m() { }
|
||||
removed: string;
|
||||
remainder: string;
|
||||
}
|
||||
var removable = new Removable();
|
||||
var { removed, ...removableRest } = removable;
|
||||
|
||||
|
||||
//// [objectRest.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};
|
||||
let o = { a: 1, b: 'no' };
|
||||
var clone = __rest(o, []);
|
||||
var { a } = o, justB = __rest(o, ["a"]);
|
||||
var { a, b: renamed } = o, empty = __rest(o, ["a", "b"]);
|
||||
var { ['b']: renamed } = o, justA = __rest(o, ["b"]);
|
||||
var { 'b': renamed } = o, justA = __rest(o, ["b"]);
|
||||
var { b: { '0': n, '1': oooo } } = o, justA = __rest(o, ["b"]);
|
||||
let o2 = { c: 'terrible idea?', d: 'yes' };
|
||||
var { d: renamed } = o2, d = __rest(o2, ["d"]);
|
||||
let nestedrest;
|
||||
var { x } = nestedrest, _a = nestedrest.n1, { y } = _a, _b = _a.n2, { z } = _b, nr = __rest(_b.n3, []), restrest = __rest(nestedrest, ["x", "n1"]);
|
||||
let complex;
|
||||
var _c = complex.x, { ka } = _c, nested = __rest(_c, ["ka"]), { y: other } = complex, rest = __rest(complex, ["x", "y"]);
|
||||
(_d = complex.x, { ka } = _d, nested = __rest(_d, ["ka"]), { y: other } = complex, rest = __rest(complex, ["x", "y"]), complex);
|
||||
var _e = { x: 1, y: 2 }, { x } = _e, fresh = __rest(_e, ["x"]);
|
||||
(_f = { x: 1, y: 2 }, { x } = _f, fresh = __rest(_f, ["x"]), _f);
|
||||
class Removable {
|
||||
set z(value) { }
|
||||
get both() { return 12; }
|
||||
set both(value) { }
|
||||
m() { }
|
||||
}
|
||||
var removable = new Removable();
|
||||
var { removed } = removable, removableRest = __rest(removable, ["removed"]);
|
||||
var _d, _f;
|
||||
146
tests/baselines/reference/objectRest.symbols
Normal file
146
tests/baselines/reference/objectRest.symbols
Normal file
@ -0,0 +1,146 @@
|
||||
=== tests/cases/conformance/types/rest/objectRest.ts ===
|
||||
let o = { a: 1, b: 'no' }
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
>a : Symbol(a, Decl(objectRest.ts, 0, 9))
|
||||
>b : Symbol(b, Decl(objectRest.ts, 0, 15))
|
||||
|
||||
var { ...clone } = o;
|
||||
>clone : Symbol(clone, Decl(objectRest.ts, 1, 5))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
var { a, ...justB } = o;
|
||||
>a : Symbol(a, Decl(objectRest.ts, 2, 5), Decl(objectRest.ts, 3, 5))
|
||||
>justB : Symbol(justB, Decl(objectRest.ts, 2, 8))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
var { a, b: renamed, ...empty } = o;
|
||||
>a : Symbol(a, Decl(objectRest.ts, 2, 5), Decl(objectRest.ts, 3, 5))
|
||||
>b : Symbol(b, Decl(objectRest.ts, 0, 15))
|
||||
>renamed : Symbol(renamed, Decl(objectRest.ts, 3, 8), Decl(objectRest.ts, 4, 5), Decl(objectRest.ts, 5, 5), Decl(objectRest.ts, 9, 5))
|
||||
>empty : Symbol(empty, Decl(objectRest.ts, 3, 20))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
var { ['b']: renamed, ...justA } = o;
|
||||
>'b' : Symbol(renamed, Decl(objectRest.ts, 3, 8), Decl(objectRest.ts, 4, 5), Decl(objectRest.ts, 5, 5), Decl(objectRest.ts, 9, 5))
|
||||
>renamed : Symbol(renamed, Decl(objectRest.ts, 3, 8), Decl(objectRest.ts, 4, 5), Decl(objectRest.ts, 5, 5), Decl(objectRest.ts, 9, 5))
|
||||
>justA : Symbol(justA, Decl(objectRest.ts, 4, 21), Decl(objectRest.ts, 5, 19), Decl(objectRest.ts, 6, 31))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
var { 'b': renamed, ...justA } = o;
|
||||
>renamed : Symbol(renamed, Decl(objectRest.ts, 3, 8), Decl(objectRest.ts, 4, 5), Decl(objectRest.ts, 5, 5), Decl(objectRest.ts, 9, 5))
|
||||
>justA : Symbol(justA, Decl(objectRest.ts, 4, 21), Decl(objectRest.ts, 5, 19), Decl(objectRest.ts, 6, 31))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
var { b: { '0': n, '1': oooo }, ...justA } = o;
|
||||
>b : Symbol(b, Decl(objectRest.ts, 0, 15))
|
||||
>n : Symbol(n, Decl(objectRest.ts, 6, 10))
|
||||
>oooo : Symbol(oooo, Decl(objectRest.ts, 6, 18))
|
||||
>justA : Symbol(justA, Decl(objectRest.ts, 4, 21), Decl(objectRest.ts, 5, 19), Decl(objectRest.ts, 6, 31))
|
||||
>o : Symbol(o, Decl(objectRest.ts, 0, 3))
|
||||
|
||||
let o2 = { c: 'terrible idea?', d: 'yes' };
|
||||
>o2 : Symbol(o2, Decl(objectRest.ts, 8, 3))
|
||||
>c : Symbol(c, Decl(objectRest.ts, 8, 10))
|
||||
>d : Symbol(d, Decl(objectRest.ts, 8, 31))
|
||||
|
||||
var { d: renamed, ...d } = o2;
|
||||
>d : Symbol(d, Decl(objectRest.ts, 8, 31))
|
||||
>renamed : Symbol(renamed, Decl(objectRest.ts, 3, 8), Decl(objectRest.ts, 4, 5), Decl(objectRest.ts, 5, 5), Decl(objectRest.ts, 9, 5))
|
||||
>d : Symbol(d, Decl(objectRest.ts, 9, 17))
|
||||
>o2 : Symbol(o2, Decl(objectRest.ts, 8, 3))
|
||||
|
||||
let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number };
|
||||
>nestedrest : Symbol(nestedrest, Decl(objectRest.ts, 11, 3))
|
||||
>x : Symbol(x, Decl(objectRest.ts, 11, 17))
|
||||
>n1 : Symbol(n1, Decl(objectRest.ts, 11, 28))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 11, 34))
|
||||
>n2 : Symbol(n2, Decl(objectRest.ts, 11, 45))
|
||||
>z : Symbol(z, Decl(objectRest.ts, 11, 51))
|
||||
>n3 : Symbol(n3, Decl(objectRest.ts, 11, 62))
|
||||
>n4 : Symbol(n4, Decl(objectRest.ts, 11, 68))
|
||||
>rest : Symbol(rest, Decl(objectRest.ts, 11, 86))
|
||||
>restrest : Symbol(restrest, Decl(objectRest.ts, 11, 100))
|
||||
|
||||
var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest;
|
||||
>x : Symbol(x, Decl(objectRest.ts, 12, 5), Decl(objectRest.ts, 17, 5))
|
||||
>n1 : Symbol(n1, Decl(objectRest.ts, 11, 28))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 12, 14))
|
||||
>n2 : Symbol(n2, Decl(objectRest.ts, 11, 45))
|
||||
>z : Symbol(z, Decl(objectRest.ts, 12, 23))
|
||||
>n3 : Symbol(n3, Decl(objectRest.ts, 11, 62))
|
||||
>nr : Symbol(nr, Decl(objectRest.ts, 12, 32))
|
||||
>restrest : Symbol(restrest, Decl(objectRest.ts, 12, 45))
|
||||
>nestedrest : Symbol(nestedrest, Decl(objectRest.ts, 11, 3))
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
>complex : Symbol(complex, Decl(objectRest.ts, 14, 3))
|
||||
>x : Symbol(x, Decl(objectRest.ts, 14, 14))
|
||||
>ka : Symbol(ka, Decl(objectRest.ts, 14, 19))
|
||||
>ki : Symbol(ki, Decl(objectRest.ts, 14, 23))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 14, 29))
|
||||
|
||||
var { x: { ka, ...nested }, y: other, ...rest } = complex;
|
||||
>x : Symbol(x, Decl(objectRest.ts, 14, 14))
|
||||
>ka : Symbol(ka, Decl(objectRest.ts, 15, 10))
|
||||
>nested : Symbol(nested, Decl(objectRest.ts, 15, 14))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 14, 29))
|
||||
>other : Symbol(other, Decl(objectRest.ts, 15, 27))
|
||||
>rest : Symbol(rest, Decl(objectRest.ts, 15, 37))
|
||||
>complex : Symbol(complex, Decl(objectRest.ts, 14, 3))
|
||||
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
>x : Symbol(x, Decl(objectRest.ts, 16, 2))
|
||||
>ka : Symbol(ka, Decl(objectRest.ts, 16, 6))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 16, 23))
|
||||
>other : Symbol(other, Decl(objectRest.ts, 15, 27))
|
||||
>complex : Symbol(complex, Decl(objectRest.ts, 14, 3))
|
||||
|
||||
var { x, ...fresh } = { x: 1, y: 2 };
|
||||
>x : Symbol(x, Decl(objectRest.ts, 12, 5), Decl(objectRest.ts, 17, 5))
|
||||
>fresh : Symbol(fresh, Decl(objectRest.ts, 17, 8))
|
||||
>x : Symbol(x, Decl(objectRest.ts, 17, 23))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 17, 29))
|
||||
|
||||
({ x, ...fresh } = { x: 1, y: 2 });
|
||||
>x : Symbol(x, Decl(objectRest.ts, 18, 2))
|
||||
>x : Symbol(x, Decl(objectRest.ts, 18, 20))
|
||||
>y : Symbol(y, Decl(objectRest.ts, 18, 26))
|
||||
|
||||
class Removable {
|
||||
>Removable : Symbol(Removable, Decl(objectRest.ts, 18, 35))
|
||||
|
||||
private x: number;
|
||||
>x : Symbol(Removable.x, Decl(objectRest.ts, 20, 17))
|
||||
|
||||
protected y: number;
|
||||
>y : Symbol(Removable.y, Decl(objectRest.ts, 21, 22))
|
||||
|
||||
set z(value: number) { }
|
||||
>z : Symbol(Removable.z, Decl(objectRest.ts, 22, 24))
|
||||
>value : Symbol(value, Decl(objectRest.ts, 23, 10))
|
||||
|
||||
get both(): number { return 12 }
|
||||
>both : Symbol(Removable.both, Decl(objectRest.ts, 23, 28), Decl(objectRest.ts, 24, 36))
|
||||
|
||||
set both(value: number) { }
|
||||
>both : Symbol(Removable.both, Decl(objectRest.ts, 23, 28), Decl(objectRest.ts, 24, 36))
|
||||
>value : Symbol(value, Decl(objectRest.ts, 25, 13))
|
||||
|
||||
m() { }
|
||||
>m : Symbol(Removable.m, Decl(objectRest.ts, 25, 31))
|
||||
|
||||
removed: string;
|
||||
>removed : Symbol(Removable.removed, Decl(objectRest.ts, 26, 11))
|
||||
|
||||
remainder: string;
|
||||
>remainder : Symbol(Removable.remainder, Decl(objectRest.ts, 27, 20))
|
||||
}
|
||||
var removable = new Removable();
|
||||
>removable : Symbol(removable, Decl(objectRest.ts, 30, 3))
|
||||
>Removable : Symbol(Removable, Decl(objectRest.ts, 18, 35))
|
||||
|
||||
var { removed, ...removableRest } = removable;
|
||||
>removed : Symbol(removed, Decl(objectRest.ts, 31, 5))
|
||||
>removableRest : Symbol(removableRest, Decl(objectRest.ts, 31, 14))
|
||||
>removable : Symbol(removable, Decl(objectRest.ts, 30, 3))
|
||||
|
||||
170
tests/baselines/reference/objectRest.types
Normal file
170
tests/baselines/reference/objectRest.types
Normal file
@ -0,0 +1,170 @@
|
||||
=== tests/cases/conformance/types/rest/objectRest.ts ===
|
||||
let o = { a: 1, b: 'no' }
|
||||
>o : { a: number; b: string; }
|
||||
>{ a: 1, b: 'no' } : { a: number; b: string; }
|
||||
>a : number
|
||||
>1 : 1
|
||||
>b : string
|
||||
>'no' : "no"
|
||||
|
||||
var { ...clone } = o;
|
||||
>clone : { a: number; b: string; }
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
var { a, ...justB } = o;
|
||||
>a : number
|
||||
>justB : { b: string; }
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
var { a, b: renamed, ...empty } = o;
|
||||
>a : number
|
||||
>b : any
|
||||
>renamed : string
|
||||
>empty : {}
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
var { ['b']: renamed, ...justA } = o;
|
||||
>'b' : "b"
|
||||
>renamed : string
|
||||
>justA : { a: number; }
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
var { 'b': renamed, ...justA } = o;
|
||||
>renamed : string
|
||||
>justA : { a: number; }
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
var { b: { '0': n, '1': oooo }, ...justA } = o;
|
||||
>b : any
|
||||
>n : string
|
||||
>oooo : string
|
||||
>justA : { a: number; }
|
||||
>o : { a: number; b: string; }
|
||||
|
||||
let o2 = { c: 'terrible idea?', d: 'yes' };
|
||||
>o2 : { c: string; d: string; }
|
||||
>{ c: 'terrible idea?', d: 'yes' } : { c: string; d: string; }
|
||||
>c : string
|
||||
>'terrible idea?' : "terrible idea?"
|
||||
>d : string
|
||||
>'yes' : "yes"
|
||||
|
||||
var { d: renamed, ...d } = o2;
|
||||
>d : any
|
||||
>renamed : string
|
||||
>d : { c: string; }
|
||||
>o2 : { c: string; d: string; }
|
||||
|
||||
let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number };
|
||||
>nestedrest : { x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; }
|
||||
>x : number
|
||||
>n1 : { y: number; n2: { z: number; n3: { n4: number; }; }; }
|
||||
>y : number
|
||||
>n2 : { z: number; n3: { n4: number; }; }
|
||||
>z : number
|
||||
>n3 : { n4: number; }
|
||||
>n4 : number
|
||||
>rest : number
|
||||
>restrest : number
|
||||
|
||||
var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest;
|
||||
>x : number
|
||||
>n1 : any
|
||||
>y : number
|
||||
>n2 : any
|
||||
>z : number
|
||||
>n3 : any
|
||||
>nr : { n4: number; }
|
||||
>restrest : { rest: number; restrest: number; }
|
||||
>nestedrest : { x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; }
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
>complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
>x : { ka: any; ki: any; }
|
||||
>ka : any
|
||||
>ki : any
|
||||
>y : number
|
||||
|
||||
var { x: { ka, ...nested }, y: other, ...rest } = complex;
|
||||
>x : any
|
||||
>ka : any
|
||||
>nested : { ki: any; }
|
||||
>y : any
|
||||
>other : number
|
||||
>rest : {}
|
||||
>complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
>({x: { ka, ...nested }, y: other, ...rest} = complex) : { x: { ka: any; ki: any; }; y: number; }
|
||||
>{x: { ka, ...nested }, y: other, ...rest} = complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
>{x: { ka, ...nested }, y: other, ...rest} : { x: { ki: any; ka: any; }; y: number; }
|
||||
>x : { ki: any; ka: any; }
|
||||
>{ ka, ...nested } : { ki: any; ka: any; }
|
||||
>ka : any
|
||||
>nested : any
|
||||
>y : number
|
||||
>other : number
|
||||
>rest : any
|
||||
>complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
|
||||
var { x, ...fresh } = { x: 1, y: 2 };
|
||||
>x : number
|
||||
>fresh : { y: number; }
|
||||
>{ x: 1, y: 2 } : { x: number; y: number; }
|
||||
>x : number
|
||||
>1 : 1
|
||||
>y : number
|
||||
>2 : 2
|
||||
|
||||
({ x, ...fresh } = { x: 1, y: 2 });
|
||||
>({ x, ...fresh } = { x: 1, y: 2 }) : { x: number; y: number; }
|
||||
>{ x, ...fresh } = { x: 1, y: 2 } : { x: number; y: number; }
|
||||
>{ x, ...fresh } : { y: number; x: number; }
|
||||
>x : number
|
||||
>fresh : any
|
||||
>{ x: 1, y: 2 } : { x: number; y: number; }
|
||||
>x : number
|
||||
>1 : 1
|
||||
>y : number
|
||||
>2 : 2
|
||||
|
||||
class Removable {
|
||||
>Removable : Removable
|
||||
|
||||
private x: number;
|
||||
>x : number
|
||||
|
||||
protected y: number;
|
||||
>y : number
|
||||
|
||||
set z(value: number) { }
|
||||
>z : number
|
||||
>value : number
|
||||
|
||||
get both(): number { return 12 }
|
||||
>both : number
|
||||
>12 : 12
|
||||
|
||||
set both(value: number) { }
|
||||
>both : number
|
||||
>value : number
|
||||
|
||||
m() { }
|
||||
>m : () => void
|
||||
|
||||
removed: string;
|
||||
>removed : string
|
||||
|
||||
remainder: string;
|
||||
>remainder : string
|
||||
}
|
||||
var removable = new Removable();
|
||||
>removable : Removable
|
||||
>new Removable() : Removable
|
||||
>Removable : typeof Removable
|
||||
|
||||
var { removed, ...removableRest } = removable;
|
||||
>removed : string
|
||||
>removableRest : { both: number; remainder: string; }
|
||||
>removable : Removable
|
||||
|
||||
35
tests/baselines/reference/objectRestAssignment.js
Normal file
35
tests/baselines/reference/objectRestAssignment.js
Normal file
@ -0,0 +1,35 @@
|
||||
//// [objectRestAssignment.ts]
|
||||
let ka: any;
|
||||
let nested: { ki };
|
||||
let other: number;
|
||||
let rest: { };
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
|
||||
// should be:
|
||||
let overEmit: { a: { ka: string, x: string }[], b: { z: string, ki: string, ku: string }, ke: string, ko: string };
|
||||
|
||||
// var _g = overEmit.a, [_h, ...y] = _g, nested2 = __rest(_h, []), _j = overEmit.b, { z } = _j, c = __rest(_j, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit;
|
||||
({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit);
|
||||
|
||||
|
||||
//// [objectRestAssignment.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};
|
||||
let ka;
|
||||
let nested;
|
||||
let other;
|
||||
let rest;
|
||||
let complex;
|
||||
(_a = complex.x, { ka } = _a, nested = __rest(_a, ["ka"]), { y: other } = complex, rest = __rest(complex, ["x", "y"]), complex);
|
||||
// should be:
|
||||
let overEmit;
|
||||
// var _g = overEmit.a, [_h, ...y] = _g, nested2 = __rest(_h, []), _j = overEmit.b, { z } = _j, c = __rest(_j, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
var _b = overEmit.a, [_c, ...y] = _b, nested2 = __rest(_c, []), _d = overEmit.b, { z } = _d, c = __rest(_d, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
(_e = overEmit.a, [_f, ...y] = _e, nested2 = __rest(_f, []), _g = overEmit.b, { z } = _g, c = __rest(_g, ["z"]), rest2 = __rest(overEmit, ["a", "b"]), overEmit);
|
||||
var _a, _e, _f, _g;
|
||||
59
tests/baselines/reference/objectRestAssignment.symbols
Normal file
59
tests/baselines/reference/objectRestAssignment.symbols
Normal file
@ -0,0 +1,59 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestAssignment.ts ===
|
||||
let ka: any;
|
||||
>ka : Symbol(ka, Decl(objectRestAssignment.ts, 0, 3))
|
||||
|
||||
let nested: { ki };
|
||||
>nested : Symbol(nested, Decl(objectRestAssignment.ts, 1, 3))
|
||||
>ki : Symbol(ki, Decl(objectRestAssignment.ts, 1, 13))
|
||||
|
||||
let other: number;
|
||||
>other : Symbol(other, Decl(objectRestAssignment.ts, 2, 3))
|
||||
|
||||
let rest: { };
|
||||
>rest : Symbol(rest, Decl(objectRestAssignment.ts, 3, 3))
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
>complex : Symbol(complex, Decl(objectRestAssignment.ts, 4, 3))
|
||||
>x : Symbol(x, Decl(objectRestAssignment.ts, 4, 14))
|
||||
>ka : Symbol(ka, Decl(objectRestAssignment.ts, 4, 19))
|
||||
>ki : Symbol(ki, Decl(objectRestAssignment.ts, 4, 23))
|
||||
>y : Symbol(y, Decl(objectRestAssignment.ts, 4, 29))
|
||||
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
>x : Symbol(x, Decl(objectRestAssignment.ts, 5, 2))
|
||||
>ka : Symbol(ka, Decl(objectRestAssignment.ts, 5, 6))
|
||||
>y : Symbol(y, Decl(objectRestAssignment.ts, 5, 23))
|
||||
>other : Symbol(other, Decl(objectRestAssignment.ts, 2, 3))
|
||||
>complex : Symbol(complex, Decl(objectRestAssignment.ts, 4, 3))
|
||||
|
||||
// should be:
|
||||
let overEmit: { a: { ka: string, x: string }[], b: { z: string, ki: string, ku: string }, ke: string, ko: string };
|
||||
>overEmit : Symbol(overEmit, Decl(objectRestAssignment.ts, 8, 3))
|
||||
>a : Symbol(a, Decl(objectRestAssignment.ts, 8, 15))
|
||||
>ka : Symbol(ka, Decl(objectRestAssignment.ts, 8, 20))
|
||||
>x : Symbol(x, Decl(objectRestAssignment.ts, 8, 32))
|
||||
>b : Symbol(b, Decl(objectRestAssignment.ts, 8, 47))
|
||||
>z : Symbol(z, Decl(objectRestAssignment.ts, 8, 52))
|
||||
>ki : Symbol(ki, Decl(objectRestAssignment.ts, 8, 63))
|
||||
>ku : Symbol(ku, Decl(objectRestAssignment.ts, 8, 75))
|
||||
>ke : Symbol(ke, Decl(objectRestAssignment.ts, 8, 89))
|
||||
>ko : Symbol(ko, Decl(objectRestAssignment.ts, 8, 101))
|
||||
|
||||
// var _g = overEmit.a, [_h, ...y] = _g, nested2 = __rest(_h, []), _j = overEmit.b, { z } = _j, c = __rest(_j, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit;
|
||||
>a : Symbol(a, Decl(objectRestAssignment.ts, 8, 15))
|
||||
>nested2 : Symbol(nested2, Decl(objectRestAssignment.ts, 11, 11))
|
||||
>y : Symbol(y, Decl(objectRestAssignment.ts, 11, 25))
|
||||
>b : Symbol(b, Decl(objectRestAssignment.ts, 8, 47))
|
||||
>z : Symbol(z, Decl(objectRestAssignment.ts, 11, 37))
|
||||
>c : Symbol(c, Decl(objectRestAssignment.ts, 11, 40))
|
||||
>rest2 : Symbol(rest2, Decl(objectRestAssignment.ts, 11, 48))
|
||||
>overEmit : Symbol(overEmit, Decl(objectRestAssignment.ts, 8, 3))
|
||||
|
||||
({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit);
|
||||
>a : Symbol(a, Decl(objectRestAssignment.ts, 12, 2))
|
||||
>y : Symbol(y, Decl(objectRestAssignment.ts, 11, 25))
|
||||
>b : Symbol(b, Decl(objectRestAssignment.ts, 12, 29))
|
||||
>z : Symbol(z, Decl(objectRestAssignment.ts, 12, 34))
|
||||
>overEmit : Symbol(overEmit, Decl(objectRestAssignment.ts, 8, 3))
|
||||
|
||||
75
tests/baselines/reference/objectRestAssignment.types
Normal file
75
tests/baselines/reference/objectRestAssignment.types
Normal file
@ -0,0 +1,75 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestAssignment.ts ===
|
||||
let ka: any;
|
||||
>ka : any
|
||||
|
||||
let nested: { ki };
|
||||
>nested : { ki: any; }
|
||||
>ki : any
|
||||
|
||||
let other: number;
|
||||
>other : number
|
||||
|
||||
let rest: { };
|
||||
>rest : {}
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
>complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
>x : { ka: any; ki: any; }
|
||||
>ka : any
|
||||
>ki : any
|
||||
>y : number
|
||||
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
>({x: { ka, ...nested }, y: other, ...rest} = complex) : { x: { ka: any; ki: any; }; y: number; }
|
||||
>{x: { ka, ...nested }, y: other, ...rest} = complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
>{x: { ka, ...nested }, y: other, ...rest} : { x: { ki: any; ka: any; }; y: number; }
|
||||
>x : { ki: any; ka: any; }
|
||||
>{ ka, ...nested } : { ki: any; ka: any; }
|
||||
>ka : any
|
||||
>nested : any
|
||||
>y : number
|
||||
>other : number
|
||||
>rest : any
|
||||
>complex : { x: { ka: any; ki: any; }; y: number; }
|
||||
|
||||
// should be:
|
||||
let overEmit: { a: { ka: string, x: string }[], b: { z: string, ki: string, ku: string }, ke: string, ko: string };
|
||||
>overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }
|
||||
>a : { ka: string; x: string; }[]
|
||||
>ka : string
|
||||
>x : string
|
||||
>b : { z: string; ki: string; ku: string; }
|
||||
>z : string
|
||||
>ki : string
|
||||
>ku : string
|
||||
>ke : string
|
||||
>ko : string
|
||||
|
||||
// var _g = overEmit.a, [_h, ...y] = _g, nested2 = __rest(_h, []), _j = overEmit.b, { z } = _j, c = __rest(_j, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit;
|
||||
>a : any
|
||||
>nested2 : { ka: string; x: string; }
|
||||
>y : { ka: string; x: string; }[]
|
||||
>b : any
|
||||
>z : string
|
||||
>c : { ki: string; ku: string; }
|
||||
>rest2 : { ke: string; ko: string; }
|
||||
>overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }
|
||||
|
||||
({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit);
|
||||
>({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit) : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }
|
||||
>{ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }
|
||||
>{ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } : { ke: string; ko: string; a: { ka: string; x: string; }[]; b: { ki: string; ku: string; z: string; }; }
|
||||
>a : { ka: string; x: string; }[]
|
||||
>[{ ...nested2 }, ...y] : { ka: string; x: string; }[]
|
||||
>{ ...nested2 } : { ka: string; x: string; }
|
||||
>nested2 : any
|
||||
>...y : { ka: string; x: string; }
|
||||
>y : { ka: string; x: string; }[]
|
||||
>b : { ki: string; ku: string; z: string; }
|
||||
>{ z, ...c } : { ki: string; ku: string; z: string; }
|
||||
>z : string
|
||||
>c : any
|
||||
>rest2 : any
|
||||
>overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }
|
||||
|
||||
45
tests/baselines/reference/objectRestForOf.js
Normal file
45
tests/baselines/reference/objectRestForOf.js
Normal file
@ -0,0 +1,45 @@
|
||||
//// [objectRestForOf.ts]
|
||||
let array: { x: number, y: string }[];
|
||||
for (let { x, ...restOf } of array) {
|
||||
[x, restOf];
|
||||
}
|
||||
let xx: number;
|
||||
let rrestOff: { y: string };
|
||||
for ({ x: xx, ...rrestOff } of array ) {
|
||||
[xx, rrestOff];
|
||||
}
|
||||
for (const norest of array.map(a => ({ ...a, x: 'a string' }))) {
|
||||
[norest.x, norest.y];
|
||||
// x is now a string. who knows why.
|
||||
}
|
||||
|
||||
|
||||
//// [objectRestForOf.js]
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};
|
||||
let array;
|
||||
for (var array_1 of array) {
|
||||
var { x } = array_1, restOf = __rest(array_1, ["x"]);
|
||||
[x, restOf];
|
||||
}
|
||||
let xx;
|
||||
let rrestOff;
|
||||
for (var array_2 of array) {
|
||||
({ x: xx } = array_2, rrestOff = __rest(array_2, ["x"]));
|
||||
[xx, rrestOff];
|
||||
}
|
||||
for (const norest of array.map(a => (__assign({}, a, { x: 'a string' })))) {
|
||||
[norest.x, norest.y];
|
||||
}
|
||||
50
tests/baselines/reference/objectRestForOf.symbols
Normal file
50
tests/baselines/reference/objectRestForOf.symbols
Normal file
@ -0,0 +1,50 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestForOf.ts ===
|
||||
let array: { x: number, y: string }[];
|
||||
>array : Symbol(array, Decl(objectRestForOf.ts, 0, 3))
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 0, 12))
|
||||
>y : Symbol(y, Decl(objectRestForOf.ts, 0, 23))
|
||||
|
||||
for (let { x, ...restOf } of array) {
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 1, 10))
|
||||
>restOf : Symbol(restOf, Decl(objectRestForOf.ts, 1, 13))
|
||||
>array : Symbol(array, Decl(objectRestForOf.ts, 0, 3))
|
||||
|
||||
[x, restOf];
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 1, 10))
|
||||
>restOf : Symbol(restOf, Decl(objectRestForOf.ts, 1, 13))
|
||||
}
|
||||
let xx: number;
|
||||
>xx : Symbol(xx, Decl(objectRestForOf.ts, 4, 3))
|
||||
|
||||
let rrestOff: { y: string };
|
||||
>rrestOff : Symbol(rrestOff, Decl(objectRestForOf.ts, 5, 3))
|
||||
>y : Symbol(y, Decl(objectRestForOf.ts, 5, 15))
|
||||
|
||||
for ({ x: xx, ...rrestOff } of array ) {
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 6, 6))
|
||||
>xx : Symbol(xx, Decl(objectRestForOf.ts, 4, 3))
|
||||
>array : Symbol(array, Decl(objectRestForOf.ts, 0, 3))
|
||||
|
||||
[xx, rrestOff];
|
||||
>xx : Symbol(xx, Decl(objectRestForOf.ts, 4, 3))
|
||||
>rrestOff : Symbol(rrestOff, Decl(objectRestForOf.ts, 5, 3))
|
||||
}
|
||||
for (const norest of array.map(a => ({ ...a, x: 'a string' }))) {
|
||||
>norest : Symbol(norest, Decl(objectRestForOf.ts, 9, 10))
|
||||
>array.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>array : Symbol(array, Decl(objectRestForOf.ts, 0, 3))
|
||||
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(objectRestForOf.ts, 9, 31))
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 9, 44))
|
||||
|
||||
[norest.x, norest.y];
|
||||
>norest.x : Symbol(x, Decl(objectRestForOf.ts, 9, 44))
|
||||
>norest : Symbol(norest, Decl(objectRestForOf.ts, 9, 10))
|
||||
>x : Symbol(x, Decl(objectRestForOf.ts, 9, 44))
|
||||
>norest.y : Symbol(y, Decl(objectRestForOf.ts, 0, 23))
|
||||
>norest : Symbol(norest, Decl(objectRestForOf.ts, 9, 10))
|
||||
>y : Symbol(y, Decl(objectRestForOf.ts, 0, 23))
|
||||
|
||||
// x is now a string. who knows why.
|
||||
}
|
||||
|
||||
61
tests/baselines/reference/objectRestForOf.types
Normal file
61
tests/baselines/reference/objectRestForOf.types
Normal file
@ -0,0 +1,61 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestForOf.ts ===
|
||||
let array: { x: number, y: string }[];
|
||||
>array : { x: number; y: string; }[]
|
||||
>x : number
|
||||
>y : string
|
||||
|
||||
for (let { x, ...restOf } of array) {
|
||||
>x : number
|
||||
>restOf : { y: string; }
|
||||
>array : { x: number; y: string; }[]
|
||||
|
||||
[x, restOf];
|
||||
>[x, restOf] : (number | { y: string; })[]
|
||||
>x : number
|
||||
>restOf : { y: string; }
|
||||
}
|
||||
let xx: number;
|
||||
>xx : number
|
||||
|
||||
let rrestOff: { y: string };
|
||||
>rrestOff : { y: string; }
|
||||
>y : string
|
||||
|
||||
for ({ x: xx, ...rrestOff } of array ) {
|
||||
>{ x: xx, ...rrestOff } : { y: string; x: number; }
|
||||
>x : { x: number; y: string; }
|
||||
>xx : number
|
||||
>rrestOff : any
|
||||
>array : { x: number; y: string; }[]
|
||||
|
||||
[xx, rrestOff];
|
||||
>[xx, rrestOff] : (number | { y: string; })[]
|
||||
>xx : number
|
||||
>rrestOff : { y: string; }
|
||||
}
|
||||
for (const norest of array.map(a => ({ ...a, x: 'a string' }))) {
|
||||
>norest : { x: string; y: string; }
|
||||
>array.map(a => ({ ...a, x: 'a string' })) : { x: string; y: string; }[]
|
||||
>array.map : { <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): U[]; }
|
||||
>array : { x: number; y: string; }[]
|
||||
>map : { <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U, U]; <U>(this: [{ x: number; y: string; }, { x: number; y: string; }], callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: { x: number; y: string; }, index: number, array: { x: number; y: string; }[]) => U, thisArg?: any): U[]; }
|
||||
>a => ({ ...a, x: 'a string' }) : (a: { x: number; y: string; }) => { x: string; y: string; }
|
||||
>a : { x: number; y: string; }
|
||||
>({ ...a, x: 'a string' }) : { x: string; y: string; }
|
||||
>{ ...a, x: 'a string' } : { x: string; y: string; }
|
||||
>a : any
|
||||
>x : string
|
||||
>'a string' : "a string"
|
||||
|
||||
[norest.x, norest.y];
|
||||
>[norest.x, norest.y] : string[]
|
||||
>norest.x : string
|
||||
>norest : { x: string; y: string; }
|
||||
>x : string
|
||||
>norest.y : string
|
||||
>norest : { x: string; y: string; }
|
||||
>y : string
|
||||
|
||||
// x is now a string. who knows why.
|
||||
}
|
||||
|
||||
21
tests/baselines/reference/objectRestNegative.errors.txt
Normal file
21
tests/baselines/reference/objectRestNegative.errors.txt
Normal file
@ -0,0 +1,21 @@
|
||||
tests/cases/conformance/types/rest/objectRestNegative.ts(2,10): error TS2462: A rest element must be last in a destructuring pattern
|
||||
tests/cases/conformance/types/rest/objectRestNegative.ts(3,31): error TS2462: A rest element must be last in a destructuring pattern
|
||||
tests/cases/conformance/types/rest/objectRestNegative.ts(6,17): error TS2700: Rest types may only be created from object types.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/rest/objectRestNegative.ts (3 errors) ====
|
||||
let o = { a: 1, b: 'no' };
|
||||
var { ...mustBeLast, a } = o;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2462: A rest element must be last in a destructuring pattern
|
||||
function stillMustBeLast({ ...mustBeLast, a }: { a: number, b: string }): void {
|
||||
~~~~~~~~~~
|
||||
!!! error TS2462: A rest element must be last in a destructuring pattern
|
||||
}
|
||||
function generic<T extends { x, y }>(t: T) {
|
||||
let { x, ...rest } = t;
|
||||
~~~~
|
||||
!!! error TS2700: Rest types may only be created from object types.
|
||||
return rest;
|
||||
}
|
||||
|
||||
27
tests/baselines/reference/objectRestNegative.js
Normal file
27
tests/baselines/reference/objectRestNegative.js
Normal file
@ -0,0 +1,27 @@
|
||||
//// [objectRestNegative.ts]
|
||||
let o = { a: 1, b: 'no' };
|
||||
var { ...mustBeLast, a } = o;
|
||||
function stillMustBeLast({ ...mustBeLast, a }: { a: number, b: string }): void {
|
||||
}
|
||||
function generic<T extends { x, y }>(t: T) {
|
||||
let { x, ...rest } = t;
|
||||
return rest;
|
||||
}
|
||||
|
||||
|
||||
//// [objectRestNegative.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};
|
||||
var o = { a: 1, b: 'no' };
|
||||
var mustBeLast = o.mustBeLast, a = o.a;
|
||||
function stillMustBeLast(_a) {
|
||||
var mustBeLast = _a.mustBeLast, a = _a.a;
|
||||
}
|
||||
function generic(t) {
|
||||
var x = t.x, rest = __rest(t, ["x"]);
|
||||
return rest;
|
||||
}
|
||||
28
tests/baselines/reference/objectRestParameter.js
Normal file
28
tests/baselines/reference/objectRestParameter.js
Normal file
@ -0,0 +1,28 @@
|
||||
//// [objectRestParameter.ts]
|
||||
function cloneAgain({ a, ...clone }: { a: number, b: string }): void {
|
||||
}
|
||||
|
||||
declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void);
|
||||
suddenly(({ x: a, ...rest }) => rest.y);
|
||||
suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka);
|
||||
|
||||
|
||||
|
||||
//// [objectRestParameter.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && !e.indexOf(p))
|
||||
t[p] = s[p];
|
||||
return t;
|
||||
};
|
||||
function cloneAgain(_a) {
|
||||
var { a } = _a, clone = __rest(_a, ["a"]);
|
||||
}
|
||||
suddenly((_a) => {
|
||||
var { x: a } = _a, rest = __rest(_a, ["x"]);
|
||||
return rest.y;
|
||||
});
|
||||
suddenly((_a = { x: { z: 1, ka: 1 }, y: 'noo' }) => {
|
||||
var _b = _a.x, { z = 12 } = _b, nested = __rest(_b, ["z"]), rest = __rest(_a, ["x"]);
|
||||
return rest.y + nested.ka;
|
||||
});
|
||||
45
tests/baselines/reference/objectRestParameter.symbols
Normal file
45
tests/baselines/reference/objectRestParameter.symbols
Normal file
@ -0,0 +1,45 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestParameter.ts ===
|
||||
function cloneAgain({ a, ...clone }: { a: number, b: string }): void {
|
||||
>cloneAgain : Symbol(cloneAgain, Decl(objectRestParameter.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(objectRestParameter.ts, 0, 21))
|
||||
>clone : Symbol(clone, Decl(objectRestParameter.ts, 0, 24))
|
||||
>a : Symbol(a, Decl(objectRestParameter.ts, 0, 38))
|
||||
>b : Symbol(b, Decl(objectRestParameter.ts, 0, 49))
|
||||
}
|
||||
|
||||
declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void);
|
||||
>suddenly : Symbol(suddenly, Decl(objectRestParameter.ts, 1, 1))
|
||||
>f : Symbol(f, Decl(objectRestParameter.ts, 3, 26))
|
||||
>a : Symbol(a, Decl(objectRestParameter.ts, 3, 30))
|
||||
>x : Symbol(x, Decl(objectRestParameter.ts, 3, 34))
|
||||
>z : Symbol(z, Decl(objectRestParameter.ts, 3, 39))
|
||||
>ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42))
|
||||
>y : Symbol(y, Decl(objectRestParameter.ts, 3, 48))
|
||||
|
||||
suddenly(({ x: a, ...rest }) => rest.y);
|
||||
>suddenly : Symbol(suddenly, Decl(objectRestParameter.ts, 1, 1))
|
||||
>x : Symbol(x, Decl(objectRestParameter.ts, 3, 34))
|
||||
>a : Symbol(a, Decl(objectRestParameter.ts, 4, 11))
|
||||
>rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17))
|
||||
>rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48))
|
||||
>rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17))
|
||||
>y : Symbol(y, Decl(objectRestParameter.ts, 3, 48))
|
||||
|
||||
suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka);
|
||||
>suddenly : Symbol(suddenly, Decl(objectRestParameter.ts, 1, 1))
|
||||
>x : Symbol(x, Decl(objectRestParameter.ts, 3, 34))
|
||||
>z : Symbol(z, Decl(objectRestParameter.ts, 5, 16))
|
||||
>nested : Symbol(nested, Decl(objectRestParameter.ts, 5, 24))
|
||||
>rest : Symbol(rest, Decl(objectRestParameter.ts, 5, 37))
|
||||
>x : Symbol(x, Decl(objectRestParameter.ts, 5, 51))
|
||||
>z : Symbol(z, Decl(objectRestParameter.ts, 5, 56))
|
||||
>ka : Symbol(ka, Decl(objectRestParameter.ts, 5, 62))
|
||||
>y : Symbol(y, Decl(objectRestParameter.ts, 5, 71))
|
||||
>rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48))
|
||||
>rest : Symbol(rest, Decl(objectRestParameter.ts, 5, 37))
|
||||
>y : Symbol(y, Decl(objectRestParameter.ts, 3, 48))
|
||||
>nested.ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42))
|
||||
>nested : Symbol(nested, Decl(objectRestParameter.ts, 5, 24))
|
||||
>ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42))
|
||||
|
||||
|
||||
56
tests/baselines/reference/objectRestParameter.types
Normal file
56
tests/baselines/reference/objectRestParameter.types
Normal file
@ -0,0 +1,56 @@
|
||||
=== tests/cases/conformance/types/rest/objectRestParameter.ts ===
|
||||
function cloneAgain({ a, ...clone }: { a: number, b: string }): void {
|
||||
>cloneAgain : ({a, ...clone}: { a: number; b: string; }) => void
|
||||
>a : number
|
||||
>clone : { b: string; }
|
||||
>a : number
|
||||
>b : string
|
||||
}
|
||||
|
||||
declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void);
|
||||
>suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any
|
||||
>f : (a: { x: { z: any; ka: any; }; y: string; }) => void
|
||||
>a : { x: { z: any; ka: any; }; y: string; }
|
||||
>x : { z: any; ka: any; }
|
||||
>z : any
|
||||
>ka : any
|
||||
>y : string
|
||||
|
||||
suddenly(({ x: a, ...rest }) => rest.y);
|
||||
>suddenly(({ x: a, ...rest }) => rest.y) : any
|
||||
>suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any
|
||||
>({ x: a, ...rest }) => rest.y : ({x: a, ...rest}: { x: { z: any; ka: any; }; y: string; }) => string
|
||||
>x : any
|
||||
>a : { z: any; ka: any; }
|
||||
>rest : { y: string; }
|
||||
>rest.y : string
|
||||
>rest : { y: string; }
|
||||
>y : string
|
||||
|
||||
suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka);
|
||||
>suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka) : any
|
||||
>suddenly : (f: (a: { x: { z: any; ka: any; }; y: string; }) => void) => any
|
||||
>({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka : ({x: {z, ...nested}, ...rest}?: { x: { z: any; ka: any; }; y: string; }) => string
|
||||
>x : any
|
||||
>z : any
|
||||
>12 : 12
|
||||
>nested : { ka: any; }
|
||||
>rest : { y: string; }
|
||||
>{ x: { z: 1, ka: 1 }, y: 'noo' } : { x: { z: number; ka: number; }; y: string; }
|
||||
>x : { z: number; ka: number; }
|
||||
>{ z: 1, ka: 1 } : { z: number; ka: number; }
|
||||
>z : number
|
||||
>1 : 1
|
||||
>ka : number
|
||||
>1 : 1
|
||||
>y : string
|
||||
>'noo' : "noo"
|
||||
>rest.y + nested.ka : string
|
||||
>rest.y : string
|
||||
>rest : { y: string; }
|
||||
>y : string
|
||||
>nested.ka : any
|
||||
>nested : { ka: any; }
|
||||
>ka : any
|
||||
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
//// [objectSpreadNoTransform.ts]
|
||||
const y = { a: 'yes', b: 'no' };
|
||||
const o = { x: 1, ...y };
|
||||
var b;
|
||||
var rest;
|
||||
({ b, ...rest } = o);
|
||||
|
||||
|
||||
//// [objectSpreadNoTransform.js]
|
||||
const y = { a: 'yes', b: 'no' };
|
||||
const o = { x: 1, ...y };
|
||||
var b;
|
||||
var rest;
|
||||
({ b, ...rest } = o);
|
||||
|
||||
@ -8,3 +8,13 @@ const o = { x: 1, ...y };
|
||||
>o : Symbol(o, Decl(objectSpreadNoTransform.ts, 1, 5))
|
||||
>x : Symbol(x, Decl(objectSpreadNoTransform.ts, 1, 11))
|
||||
|
||||
var b;
|
||||
>b : Symbol(b, Decl(objectSpreadNoTransform.ts, 2, 3))
|
||||
|
||||
var rest;
|
||||
>rest : Symbol(rest, Decl(objectSpreadNoTransform.ts, 3, 3))
|
||||
|
||||
({ b, ...rest } = o);
|
||||
>b : Symbol(b, Decl(objectSpreadNoTransform.ts, 4, 2))
|
||||
>o : Symbol(o, Decl(objectSpreadNoTransform.ts, 1, 5))
|
||||
|
||||
|
||||
@ -14,3 +14,17 @@ const o = { x: 1, ...y };
|
||||
>1 : 1
|
||||
>y : any
|
||||
|
||||
var b;
|
||||
>b : any
|
||||
|
||||
var rest;
|
||||
>rest : any
|
||||
|
||||
({ b, ...rest } = o);
|
||||
>({ b, ...rest } = o) : { a: string; b: string; x: number; }
|
||||
>{ b, ...rest } = o : { a: string; b: string; x: number; }
|
||||
>{ b, ...rest } : any
|
||||
>b : any
|
||||
>rest : any
|
||||
>o : { a: string; b: string; x: number; }
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts(1,9): error TS2462: A rest element must be last in an array destructuring pattern
|
||||
tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts(2,2): error TS2462: A rest element must be last in an array destructuring pattern
|
||||
tests/cases/conformance/types/rest/restElementMustBeLast.ts(1,9): error TS2462: A rest element must be last in a destructuring pattern
|
||||
tests/cases/conformance/types/rest/restElementMustBeLast.ts(2,2): error TS2462: A rest element must be last in a destructuring pattern
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/restElementMustBeLast.ts (2 errors) ====
|
||||
==== tests/cases/conformance/types/rest/restElementMustBeLast.ts (2 errors) ====
|
||||
var [...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
~
|
||||
!!! error TS2462: A rest element must be last in an array destructuring pattern
|
||||
!!! error TS2462: A rest element must be last in a destructuring pattern
|
||||
[...a, x] = [1, 2, 3]; // Error, rest must be last element
|
||||
~~~~
|
||||
!!! error TS2462: A rest element must be last in an array destructuring pattern
|
||||
!!! error TS2462: A rest element must be last in a destructuring pattern
|
||||
|
||||
@ -194,13 +194,13 @@ for (_b = getRobot(), _c = _b.name, nameA = _c === void 0 ? "noName" : _c, _b, i
|
||||
for (_d = { name: "trimmer", skill: "trimming" }, _e = _d.name, nameA = _e === void 0 ? "noName" : _e, _d, i = 0; i < 1; i++) {
|
||||
console.log(nameA);
|
||||
}
|
||||
for (_f = multiRobot.skills, _g = _f === void 0 ? { primary: "none", secondary: "none" } : _f, _h = _g.primary, primaryA = _h === void 0 ? "primary" : _h, _j = _g.secondary, secondaryA = _j === void 0 ? "secondary" : _j, multiRobot, i = 0; i < 1; i++) {
|
||||
for (_f = multiRobot.skills, _g = _f === void 0 ? { primary: "none", secondary: "none" } : _f, _h = _g.primary, primaryA = _h === void 0 ? "primary" : _h, _j = _g.secondary, secondaryA = _j === void 0 ? "secondary" : _j, multiRobot, multiRobot, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_k = getMultiRobot(), _l = _k.skills, _m = _l === void 0 ? { primary: "none", secondary: "none" } : _l, _o = _m.primary, primaryA = _o === void 0 ? "primary" : _o, _p = _m.secondary, secondaryA = _p === void 0 ? "secondary" : _p, _k, i = 0; i < 1; i++) {
|
||||
for (_k = getMultiRobot(), (_l = _k.skills, _m = _l === void 0 ? { primary: "none", secondary: "none" } : _l, _o = _m.primary, primaryA = _o === void 0 ? "primary" : _o, _p = _m.secondary, secondaryA = _p === void 0 ? "secondary" : _p, _k), _k, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_q = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, _r = _q.skills, _s = _r === void 0 ? { primary: "none", secondary: "none" } : _r, _t = _s.primary, primaryA = _t === void 0 ? "primary" : _t, _u = _s.secondary, secondaryA = _u === void 0 ? "secondary" : _u, _q,
|
||||
for (_q = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, (_r = _q.skills, _s = _r === void 0 ? { primary: "none", secondary: "none" } : _r, _t = _s.primary, primaryA = _t === void 0 ? "primary" : _t, _u = _s.secondary, secondaryA = _u === void 0 ? "secondary" : _u, _q), _q,
|
||||
i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
@ -213,13 +213,13 @@ for (_w = getRobot(), _x = _w.name, name = _x === void 0 ? "noName" : _x, _w, i
|
||||
for (_y = { name: "trimmer", skill: "trimming" }, _z = _y.name, name = _z === void 0 ? "noName" : _z, _y, i = 0; i < 1; i++) {
|
||||
console.log(nameA);
|
||||
}
|
||||
for (_0 = multiRobot.skills, _1 = _0 === void 0 ? { primary: "none", secondary: "none" } : _0, _2 = _1.primary, primary = _2 === void 0 ? "primary" : _2, _3 = _1.secondary, secondary = _3 === void 0 ? "secondary" : _3, multiRobot, i = 0; i < 1; i++) {
|
||||
for (_0 = multiRobot.skills, _1 = _0 === void 0 ? { primary: "none", secondary: "none" } : _0, _2 = _1.primary, primary = _2 === void 0 ? "primary" : _2, _3 = _1.secondary, secondary = _3 === void 0 ? "secondary" : _3, multiRobot, multiRobot, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_4 = getMultiRobot(), _5 = _4.skills, _6 = _5 === void 0 ? { primary: "none", secondary: "none" } : _5, _7 = _6.primary, primary = _7 === void 0 ? "primary" : _7, _8 = _6.secondary, secondary = _8 === void 0 ? "secondary" : _8, _4, i = 0; i < 1; i++) {
|
||||
for (_4 = getMultiRobot(), (_5 = _4.skills, _6 = _5 === void 0 ? { primary: "none", secondary: "none" } : _5, _7 = _6.primary, primary = _7 === void 0 ? "primary" : _7, _8 = _6.secondary, secondary = _8 === void 0 ? "secondary" : _8, _4), _4, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_9 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, _10 = _9.skills, _11 = _10 === void 0 ? { primary: "none", secondary: "none" } : _10, _12 = _11.primary, primary = _12 === void 0 ? "primary" : _12, _13 = _11.secondary, secondary = _13 === void 0 ? "secondary" : _13, _9,
|
||||
for (_9 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, (_10 = _9.skills, _11 = _10 === void 0 ? { primary: "none", secondary: "none" } : _10, _12 = _11.primary, primary = _12 === void 0 ? "primary" : _12, _13 = _11.secondary, secondary = _13 === void 0 ? "secondary" : _13, _9), _9,
|
||||
i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
@ -232,13 +232,13 @@ for (_16 = getRobot(), _17 = _16.name, nameA = _17 === void 0 ? "noName" : _17,
|
||||
for (_19 = { name: "trimmer", skill: "trimming" }, _20 = _19.name, nameA = _20 === void 0 ? "noName" : _20, _21 = _19.skill, skillA = _21 === void 0 ? "skill" : _21, _19, i = 0; i < 1; i++) {
|
||||
console.log(nameA);
|
||||
}
|
||||
for (_22 = multiRobot.name, nameA = _22 === void 0 ? "noName" : _22, _23 = multiRobot.skills, _24 = _23 === void 0 ? { primary: "none", secondary: "none" } : _23, _25 = _24.primary, primaryA = _25 === void 0 ? "primary" : _25, _26 = _24.secondary, secondaryA = _26 === void 0 ? "secondary" : _26, multiRobot, i = 0; i < 1; i++) {
|
||||
for (_22 = multiRobot.name, nameA = _22 === void 0 ? "noName" : _22, _23 = multiRobot.skills, _24 = _23 === void 0 ? { primary: "none", secondary: "none" } : _23, _25 = _24.primary, primaryA = _25 === void 0 ? "primary" : _25, _26 = _24.secondary, secondaryA = _26 === void 0 ? "secondary" : _26, multiRobot, multiRobot, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_27 = getMultiRobot(), _28 = _27.name, nameA = _28 === void 0 ? "noName" : _28, _29 = _27.skills, _30 = _29 === void 0 ? { primary: "none", secondary: "none" } : _29, _31 = _30.primary, primaryA = _31 === void 0 ? "primary" : _31, _32 = _30.secondary, secondaryA = _32 === void 0 ? "secondary" : _32, _27, i = 0; i < 1; i++) {
|
||||
for (_27 = getMultiRobot(), (_28 = _27.name, nameA = _28 === void 0 ? "noName" : _28, _29 = _27.skills, _30 = _29 === void 0 ? { primary: "none", secondary: "none" } : _29, _31 = _30.primary, primaryA = _31 === void 0 ? "primary" : _31, _32 = _30.secondary, secondaryA = _32 === void 0 ? "secondary" : _32, _27), _27, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_33 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, _34 = _33.name, nameA = _34 === void 0 ? "noName" : _34, _35 = _33.skills, _36 = _35 === void 0 ? { primary: "none", secondary: "none" } : _35, _37 = _36.primary, primaryA = _37 === void 0 ? "primary" : _37, _38 = _36.secondary, secondaryA = _38 === void 0 ? "secondary" : _38, _33,
|
||||
for (_33 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, (_34 = _33.name, nameA = _34 === void 0 ? "noName" : _34, _35 = _33.skills, _36 = _35 === void 0 ? { primary: "none", secondary: "none" } : _35, _37 = _36.primary, primaryA = _37 === void 0 ? "primary" : _37, _38 = _36.secondary, secondaryA = _38 === void 0 ? "secondary" : _38, _33), _33,
|
||||
i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
@ -251,15 +251,16 @@ for (_41 = getRobot(), _42 = _41.name, name = _42 === void 0 ? "noName" : _42, _
|
||||
for (_44 = { name: "trimmer", skill: "trimming" }, _45 = _44.name, name = _45 === void 0 ? "noName" : _45, _46 = _44.skill, skill = _46 === void 0 ? "skill" : _46, _44, i = 0; i < 1; i++) {
|
||||
console.log(nameA);
|
||||
}
|
||||
for (_47 = multiRobot.name, name = _47 === void 0 ? "noName" : _47, _48 = multiRobot.skills, _49 = _48 === void 0 ? { primary: "none", secondary: "none" } : _48, _50 = _49.primary, primary = _50 === void 0 ? "primary" : _50, _51 = _49.secondary, secondary = _51 === void 0 ? "secondary" : _51, multiRobot, i = 0; i < 1; i++) {
|
||||
for (_47 = multiRobot.name, name = _47 === void 0 ? "noName" : _47, _48 = multiRobot.skills, _49 = _48 === void 0 ? { primary: "none", secondary: "none" } : _48, _50 = _49.primary, primary = _50 === void 0 ? "primary" : _50, _51 = _49.secondary, secondary = _51 === void 0 ? "secondary" : _51, multiRobot, multiRobot, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_52 = getMultiRobot(), _53 = _52.name, name = _53 === void 0 ? "noName" : _53, _54 = _52.skills, _55 = _54 === void 0 ? { primary: "none", secondary: "none" } : _54, _56 = _55.primary, primary = _56 === void 0 ? "primary" : _56, _57 = _55.secondary, secondary = _57 === void 0 ? "secondary" : _57, _52, i = 0; i < 1; i++) {
|
||||
for (_52 = getMultiRobot(), (_53 = _52.name, name = _53 === void 0 ? "noName" : _53, _54 = _52.skills, _55 = _54 === void 0 ? { primary: "none", secondary: "none" } : _54, _56 = _55.primary, primary = _56 === void 0 ? "primary" : _56, _57 = _55.secondary, secondary = _57 === void 0 ? "secondary" : _57, _52), _52, i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
for (_58 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, _59 = _58.name, name = _59 === void 0 ? "noName" : _59, _60 = _58.skills, _61 = _60 === void 0 ? { primary: "none", secondary: "none" } : _60, _62 = _61.primary, primary = _62 === void 0 ? "primary" : _62, _63 = _61.secondary, secondary = _63 === void 0 ? "secondary" : _63, _58,
|
||||
for (_58 = { name: "trimmer", skills: { primary: "trimming", secondary: "edging" } }, (_59 = _58.name, name = _59 === void 0 ? "noName" : _59, _60 = _58.skills, _61 = _60 === void 0 ? { primary: "none", secondary: "none" } : _60, _62 = _61.primary, primary = _62 === void 0 ? "primary" : _62, _63 = _61.secondary, secondary = _63 === void 0 ? "secondary" : _63, _58), _58,
|
||||
i = 0; i < 1; i++) {
|
||||
console.log(primaryA);
|
||||
}
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63;
|
||||
var _k, _q, _4, _9, _27, _33, _52, _58;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _l, _m, _o, _p, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _5, _6, _7, _8, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _28, _29, _30, _31, _32, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _53, _54, _55, _56, _57, _59, _60, _61, _62, _63;
|
||||
//# sourceMappingURL=sourceMapValidationDestructuringForObjectBindingPatternDefaultValues2.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
33
tests/cases/conformance/types/rest/objectRest.ts
Normal file
33
tests/cases/conformance/types/rest/objectRest.ts
Normal file
@ -0,0 +1,33 @@
|
||||
// @target: es2015
|
||||
let o = { a: 1, b: 'no' }
|
||||
var { ...clone } = o;
|
||||
var { a, ...justB } = o;
|
||||
var { a, b: renamed, ...empty } = o;
|
||||
var { ['b']: renamed, ...justA } = o;
|
||||
var { 'b': renamed, ...justA } = o;
|
||||
var { b: { '0': n, '1': oooo }, ...justA } = o;
|
||||
|
||||
let o2 = { c: 'terrible idea?', d: 'yes' };
|
||||
var { d: renamed, ...d } = o2;
|
||||
|
||||
let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number };
|
||||
var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest;
|
||||
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
var { x: { ka, ...nested }, y: other, ...rest } = complex;
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
var { x, ...fresh } = { x: 1, y: 2 };
|
||||
({ x, ...fresh } = { x: 1, y: 2 });
|
||||
|
||||
class Removable {
|
||||
private x: number;
|
||||
protected y: number;
|
||||
set z(value: number) { }
|
||||
get both(): number { return 12 }
|
||||
set both(value: number) { }
|
||||
m() { }
|
||||
removed: string;
|
||||
remainder: string;
|
||||
}
|
||||
var removable = new Removable();
|
||||
var { removed, ...removableRest } = removable;
|
||||
14
tests/cases/conformance/types/rest/objectRestAssignment.ts
Normal file
14
tests/cases/conformance/types/rest/objectRestAssignment.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// @target: es2015
|
||||
let ka: any;
|
||||
let nested: { ki };
|
||||
let other: number;
|
||||
let rest: { };
|
||||
let complex: { x: { ka, ki }, y: number };
|
||||
({x: { ka, ...nested }, y: other, ...rest} = complex);
|
||||
|
||||
// should be:
|
||||
let overEmit: { a: { ka: string, x: string }[], b: { z: string, ki: string, ku: string }, ke: string, ko: string };
|
||||
|
||||
// var _g = overEmit.a, [_h, ...y] = _g, nested2 = __rest(_h, []), _j = overEmit.b, { z } = _j, c = __rest(_j, ["z"]), rest2 = __rest(overEmit, ["a", "b"]);
|
||||
var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit;
|
||||
({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit);
|
||||
14
tests/cases/conformance/types/rest/objectRestForOf.ts
Normal file
14
tests/cases/conformance/types/rest/objectRestForOf.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// @target: es2015
|
||||
let array: { x: number, y: string }[];
|
||||
for (let { x, ...restOf } of array) {
|
||||
[x, restOf];
|
||||
}
|
||||
let xx: number;
|
||||
let rrestOff: { y: string };
|
||||
for ({ x: xx, ...rrestOff } of array ) {
|
||||
[xx, rrestOff];
|
||||
}
|
||||
for (const norest of array.map(a => ({ ...a, x: 'a string' }))) {
|
||||
[norest.x, norest.y];
|
||||
// x is now a string. who knows why.
|
||||
}
|
||||
8
tests/cases/conformance/types/rest/objectRestNegative.ts
Normal file
8
tests/cases/conformance/types/rest/objectRestNegative.ts
Normal file
@ -0,0 +1,8 @@
|
||||
let o = { a: 1, b: 'no' };
|
||||
var { ...mustBeLast, a } = o;
|
||||
function stillMustBeLast({ ...mustBeLast, a }: { a: number, b: string }): void {
|
||||
}
|
||||
function generic<T extends { x, y }>(t: T) {
|
||||
let { x, ...rest } = t;
|
||||
return rest;
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
// @target: es2015
|
||||
function cloneAgain({ a, ...clone }: { a: number, b: string }): void {
|
||||
}
|
||||
|
||||
declare function suddenly(f: (a: { x: { z, ka }, y: string }) => void);
|
||||
suddenly(({ x: a, ...rest }) => rest.y);
|
||||
suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka);
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// @target: esnext
|
||||
const y = { a: 'yes', b: 'no' };
|
||||
const o = { x: 1, ...y };
|
||||
var b;
|
||||
var rest;
|
||||
({ b, ...rest } = o);
|
||||
|
||||
13
tests/cases/fourslash/completionListForRest.ts
Normal file
13
tests/cases/fourslash/completionListForRest.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
////interface Gen {
|
||||
//// x: number;
|
||||
//// parent: Gen;
|
||||
//// millenial: string;
|
||||
////}
|
||||
////let t: Gen;
|
||||
////var { x, ...rest } = t;
|
||||
////rest./*1*/x;
|
||||
goTo.marker('1');
|
||||
verify.memberListContains('parent', '(property) Gen.parent: Gen');
|
||||
verify.memberListContains('millenial', '(property) Gen.millenial: string');
|
||||
verify.memberListCount(2);
|
||||
12
tests/cases/fourslash/findAllRefsForRest.ts
Normal file
12
tests/cases/fourslash/findAllRefsForRest.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
////interface Gen {
|
||||
//// x: number
|
||||
//// [|parent|]: Gen;
|
||||
//// millenial: string;
|
||||
////}
|
||||
////let t: Gen;
|
||||
////var { x, ...rest } = t;
|
||||
////rest.[|parent|];
|
||||
const ranges = test.ranges();
|
||||
verify.referencesOf(ranges[0], ranges);
|
||||
verify.referencesOf(ranges[1], ranges);
|
||||
12
tests/cases/fourslash/goToDefinitionRest.ts
Normal file
12
tests/cases/fourslash/goToDefinitionRest.ts
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
/// <reference path='fourslash.ts'/>
|
||||
////interface Gen {
|
||||
//// x: number;
|
||||
//// /*1*/parent: Gen;
|
||||
//// millenial: string;
|
||||
////}
|
||||
////let t: Gen;
|
||||
////var { x, ...rest } = t;
|
||||
////rest./*2*/parent;
|
||||
const ranges = test.ranges();
|
||||
verify.goToDefinition('2', [ '1' ]);
|
||||
15
tests/cases/fourslash/renameRest.ts
Normal file
15
tests/cases/fourslash/renameRest.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
////interface Gen {
|
||||
//// x: number;
|
||||
//// [|parent|]: Gen;
|
||||
//// millenial: string;
|
||||
////}
|
||||
////let t: Gen;
|
||||
////var { x, ...rest } = t;
|
||||
////rest.[|parent|];
|
||||
const ranges = test.ranges();
|
||||
verify.assertHasRanges(ranges);
|
||||
goTo.position(ranges[0].start);
|
||||
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false, ranges);
|
||||
goTo.position(ranges[1].start);
|
||||
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false, ranges);
|
||||
Loading…
x
Reference in New Issue
Block a user