mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-17 19:11:26 -06:00
Clean up destructuring
This commit is contained in:
parent
d5b9263433
commit
08f467bd4c
@ -1280,7 +1280,7 @@ namespace ts {
|
||||
function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) {
|
||||
const name = !isOmittedExpression(node) ? node.name : undefined;
|
||||
if (isBindingPattern(name)) {
|
||||
for (const child of name.elements) {
|
||||
for (const child of <ArrayBindingElement[]>name.elements) {
|
||||
bindInitializedVariableFlow(child);
|
||||
}
|
||||
}
|
||||
@ -2629,7 +2629,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// parameters with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) {
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
@ -2867,7 +2867,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) {
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
@ -2909,7 +2909,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// function expressions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) {
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
@ -2952,7 +2952,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// arrow functions with object rest destructuring are ES Next syntax
|
||||
if (subtreeFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) {
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
@ -2982,16 +2982,11 @@ namespace ts {
|
||||
|
||||
function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
const nameKind = node.name.kind;
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
|
||||
// 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;
|
||||
// A VariableDeclaration containing ObjectRest is ESNext syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// Type annotations are TypeScript syntax.
|
||||
@ -3213,13 +3208,6 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsSpread | TransformFlags.ContainsObjectSpread;
|
||||
break;
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
if ((<BindingElement>node).dotDotDotToken) {
|
||||
transformFlags |= TransformFlags.ContainsRest;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@ -3232,7 +3220,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
if (subtreeFlags & TransformFlags.ContainsSpread) {
|
||||
if (subtreeFlags & TransformFlags.ContainsRest) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRest;
|
||||
}
|
||||
excludeFlags = TransformFlags.BindingPatternExcludes;
|
||||
@ -3243,6 +3231,13 @@ namespace ts {
|
||||
excludeFlags = TransformFlags.BindingPatternExcludes;
|
||||
break;
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
if ((<BindingElement>node).dotDotDotToken) {
|
||||
transformFlags |= TransformFlags.ContainsRest;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
// This node is TypeScript syntax, and marks its container as also being TypeScript syntax.
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsDecorators;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,80 +3,21 @@
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
type EffectiveBindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | BindingElement | ObjectLiteralElementLike | Expression;
|
||||
type EffectiveObjectBindingOrAssignmentPattern = ObjectBindingPattern | ObjectLiteralExpression;
|
||||
type EffectiveArrayBindingOrAssignmentPattern = ArrayBindingPattern | ArrayLiteralExpression;
|
||||
type EffectiveBindingOrAssignmentPattern = EffectiveObjectBindingOrAssignmentPattern | EffectiveArrayBindingOrAssignmentPattern;
|
||||
type EffectiveBindingOrAssignmentTarget = EffectiveBindingOrAssignmentPattern | Expression;
|
||||
type EffectiveBindingOrAssignmentRestIndicator = DotDotDotToken | SpreadElement | SpreadAssignment;
|
||||
|
||||
interface FlattenHost {
|
||||
context: TransformationContext;
|
||||
level: FlattenLevel;
|
||||
recordTempVariablesInLine: boolean;
|
||||
emitExpression: (value: Expression) => void;
|
||||
emitBindingOrAssignment: (target: EffectiveBindingOrAssignmentTarget, value: Expression, location: TextRange, original: Node) => void;
|
||||
createArrayBindingOrAssignmentPattern: (elements: EffectiveBindingOrAssignmentElement[]) => EffectiveArrayBindingOrAssignmentPattern;
|
||||
createObjectBindingOrAssignmentPattern: (elements: EffectiveBindingOrAssignmentElement[]) => EffectiveObjectBindingOrAssignmentPattern;
|
||||
createArrayBindingOrAssignmentElement: (node: Identifier) => EffectiveBindingOrAssignmentElement;
|
||||
emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void;
|
||||
createArrayBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ArrayBindingOrAssignmentPattern;
|
||||
createObjectBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ObjectBindingOrAssignmentPattern;
|
||||
createArrayBindingOrAssignmentElement: (node: Identifier) => BindingOrAssignmentElement;
|
||||
visitor?: (node: Node) => VisitResult<Node>;
|
||||
}
|
||||
|
||||
export const enum FlattenLevel {
|
||||
ObjectRest,
|
||||
All,
|
||||
}
|
||||
|
||||
export const enum FlattenOutput {
|
||||
Expression,
|
||||
Declarations
|
||||
}
|
||||
|
||||
export const enum FlattenOptions {
|
||||
NeedsValue = 1 << 0,
|
||||
SkipInitializer = 1 << 1,
|
||||
RecordTempVariablesInLine = 1 << 2,
|
||||
}
|
||||
|
||||
export function flattenDestructuring(
|
||||
output: FlattenOutput.Expression,
|
||||
level: FlattenLevel,
|
||||
node: VariableDeclaration | DestructuringAssignment,
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
context: TransformationContext,
|
||||
options: FlattenOptions,
|
||||
createAssignment?: (name: Identifier, value: Expression, location?: TextRange) => Expression): Expression;
|
||||
export function flattenDestructuring(
|
||||
output: FlattenOutput.Declarations,
|
||||
level: FlattenLevel,
|
||||
node: VariableDeclaration | ParameterDeclaration,
|
||||
visitor: (node: Node) => VisitResult<Node>,
|
||||
context: TransformationContext,
|
||||
options: FlattenOptions,
|
||||
boundValue?: Expression): VariableDeclaration[];
|
||||
export function flattenDestructuring(
|
||||
_output: FlattenOutput,
|
||||
_level: FlattenLevel,
|
||||
_node: VariableDeclaration | ParameterDeclaration | DestructuringAssignment,
|
||||
_visitor: (node: Node) => VisitResult<Node>,
|
||||
_context: TransformationContext,
|
||||
_options: FlattenOptions,
|
||||
_valueOrCallback?: Expression | ((name: Identifier, value: Expression, location?: TextRange) => Expression)): Expression | VariableDeclaration[] {
|
||||
// const flattenMode = flags & FlattenFlags.FlattenMask;
|
||||
// const outputMode = flags & FlattenFlags.OutputMask;
|
||||
// const options = flags & FlattenFlags.OptionsMask;
|
||||
|
||||
|
||||
// if (outputMode === FlattenFlags.OutputExpressions) {
|
||||
// return flattenDestructuringToExpression(context, <VariableDeclaration | DestructuringAssignment>node, !(options & FlattenFlags.NeedsValue), flattenMode, createAssignmentCallback, visitor);
|
||||
// }
|
||||
// else {
|
||||
// return flattenDestructuringToDeclarations(
|
||||
// context,
|
||||
// <VariableDeclaration | ParameterDeclaration>node,
|
||||
// boundValue)
|
||||
// }
|
||||
return;
|
||||
ObjectRest,
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +31,7 @@ namespace ts {
|
||||
* @param createAssignmentCallback A callback used to create the assignment expression.
|
||||
* @param visitor A visitor used to visit initializers.
|
||||
*/
|
||||
export function flattenDestructuringToExpression(
|
||||
export function flattenDestructuringAssignment(
|
||||
context: TransformationContext,
|
||||
node: VariableDeclaration | DestructuringAssignment,
|
||||
needsValue: boolean,
|
||||
@ -120,9 +61,9 @@ namespace ts {
|
||||
recordTempVariablesInLine: false,
|
||||
emitExpression,
|
||||
emitBindingOrAssignment,
|
||||
createArrayBindingOrAssignmentPattern: createEffectiveArrayAssignmentPattern,
|
||||
createObjectBindingOrAssignmentPattern: createEffectiveObjectAssignmentPattern,
|
||||
createArrayBindingOrAssignmentElement: createEffectiveAssignmentElement,
|
||||
createArrayBindingOrAssignmentPattern: makeArrayAssignmentPattern,
|
||||
createObjectBindingOrAssignmentPattern: makeObjectAssignmentPattern,
|
||||
createArrayBindingOrAssignmentElement: makeAssignmentElement,
|
||||
visitor
|
||||
};
|
||||
|
||||
@ -148,7 +89,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
flattenEffectiveBindingElement(host, node, value, location, /*skipInitializer*/ isDestructuringAssignment(node));
|
||||
flattenBindingOrAssignmentElement(host, node, value, location, /*skipInitializer*/ isDestructuringAssignment(node));
|
||||
|
||||
if (value && needsValue) {
|
||||
expressions.push(value);
|
||||
@ -164,7 +105,7 @@ namespace ts {
|
||||
expressions.push(expression);
|
||||
}
|
||||
|
||||
function emitBindingOrAssignment(target: EffectiveBindingOrAssignmentTarget, value: Expression, location: TextRange, original: Node) {
|
||||
function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) {
|
||||
Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression);
|
||||
const expression = createAssignmentCallback
|
||||
? createAssignmentCallback(<Identifier>target, value, location)
|
||||
@ -183,7 +124,7 @@ namespace ts {
|
||||
* @param recordTempVariablesInLine Indicates whether temporary variables should be recored in-line.
|
||||
* @param level Indicates the extent to which flattening should occur.
|
||||
*/
|
||||
export function flattenDestructuringToDeclarations(
|
||||
export function flattenDestructuringBinding(
|
||||
context: TransformationContext,
|
||||
node: VariableDeclaration | ParameterDeclaration,
|
||||
boundValue: Expression | undefined,
|
||||
@ -201,13 +142,13 @@ namespace ts {
|
||||
recordTempVariablesInLine,
|
||||
emitExpression,
|
||||
emitBindingOrAssignment,
|
||||
createArrayBindingOrAssignmentPattern: createEffectiveArrayBindingPattern,
|
||||
createObjectBindingOrAssignmentPattern: createEffectiveObjectBindingPattern,
|
||||
createArrayBindingOrAssignmentElement: createEffectiveBindingElement,
|
||||
createArrayBindingOrAssignmentPattern: makeArrayBindingPattern,
|
||||
createObjectBindingOrAssignmentPattern: makeObjectBindingPattern,
|
||||
createArrayBindingOrAssignmentElement: makeBindingElement,
|
||||
visitor
|
||||
};
|
||||
|
||||
flattenEffectiveBindingElement(host, node, boundValue, node, skipInitializer);
|
||||
flattenBindingOrAssignmentElement(host, node, boundValue, node, skipInitializer);
|
||||
|
||||
if (pendingExpressions) {
|
||||
const temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
@ -248,7 +189,7 @@ namespace ts {
|
||||
pendingExpressions = append(pendingExpressions, value);
|
||||
}
|
||||
|
||||
function emitBindingOrAssignment(target: EffectiveBindingOrAssignmentTarget, value: Expression, location: TextRange, original: Node) {
|
||||
function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) {
|
||||
Debug.assertNode(target, isBindingName);
|
||||
if (pendingExpressions) {
|
||||
value = inlineExpressions(append(pendingExpressions, value));
|
||||
@ -258,14 +199,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function flattenEffectiveBindingElement(
|
||||
function flattenBindingOrAssignmentElement(
|
||||
host: FlattenHost,
|
||||
bindingElement: EffectiveBindingOrAssignmentElement,
|
||||
bindingElement: BindingOrAssignmentElement,
|
||||
boundValue: Expression | undefined,
|
||||
location: TextRange,
|
||||
skipInitializer?: boolean) {
|
||||
if (!skipInitializer) {
|
||||
const initializer = visitNode(getInitializerOfEffectiveBindingElement(bindingElement), host.visitor, isExpression);
|
||||
const initializer = visitNode(getInitializerOfBindingOrAssignmentElement(bindingElement), host.visitor, isExpression);
|
||||
if (initializer) {
|
||||
// Combine value and initializer
|
||||
boundValue = boundValue ? createDefaultValueCheck(host, boundValue, initializer, location) : initializer;
|
||||
@ -275,39 +216,36 @@ namespace ts {
|
||||
boundValue = createVoidZero();
|
||||
}
|
||||
}
|
||||
const bindingTarget = getTargetOfEffectiveBindingElement(bindingElement);
|
||||
if (!isEffectiveBindingPattern(bindingTarget)) {
|
||||
host.emitBindingOrAssignment(bindingTarget, boundValue, location, /*original*/ bindingElement);
|
||||
const bindingTarget = getTargetOfBindingOrAssignmentElement(bindingElement);
|
||||
if (isObjectBindingOrAssignmentPattern(bindingTarget)) {
|
||||
flattenObjectBindingOrAssignmentPattern(host, bindingElement, bindingTarget, boundValue, location);
|
||||
}
|
||||
else if (isArrayBindingOrAssignmentPattern(bindingTarget)) {
|
||||
flattenArrayBindingOrAssignmentPattern(host, bindingElement, bindingTarget, boundValue, location);
|
||||
}
|
||||
else {
|
||||
const elements = getElementsOfEffectiveBindingPattern(bindingTarget);
|
||||
const numElements = 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
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(bindingElement) || numElements !== 0;
|
||||
boundValue = ensureIdentifier(host, boundValue, reuseIdentifierExpressions, location);
|
||||
}
|
||||
if (isEffectiveObjectBindingPattern(bindingTarget)) {
|
||||
flattenEffectiveObjectBindingElements(host, bindingTarget, elements, boundValue, location);
|
||||
}
|
||||
else {
|
||||
flattenEffectiveArrayBindingElements(host, bindingTarget, elements, boundValue, location);
|
||||
}
|
||||
host.emitBindingOrAssignment(bindingTarget, boundValue, location, /*original*/ bindingElement);
|
||||
}
|
||||
}
|
||||
|
||||
function flattenEffectiveObjectBindingElements(host: FlattenHost, bindingTarget: EffectiveObjectBindingOrAssignmentPattern, elements: EffectiveBindingOrAssignmentElement[], boundValue: Expression, location: TextRange) {
|
||||
let bindingElements: EffectiveBindingOrAssignmentElement[];
|
||||
function flattenObjectBindingOrAssignmentPattern(host: FlattenHost, parentElement: BindingOrAssignmentElement, bindingTarget: ObjectBindingOrAssignmentPattern, boundValue: Expression, location: TextRange) {
|
||||
const elements = getElementsOfBindingOrAssignmentPattern(bindingTarget);
|
||||
const numElements = 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
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(parentElement) || numElements !== 0;
|
||||
boundValue = ensureIdentifier(host, boundValue, reuseIdentifierExpressions, location);
|
||||
}
|
||||
let bindingElements: BindingOrAssignmentElement[];
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (!getEffectiveRestIndicator(element)) {
|
||||
if (host.level <= FlattenLevel.ObjectRest
|
||||
if (!getRestIndicatorOfBindingOrAssignmentElement(element)) {
|
||||
if (host.level >= FlattenLevel.ObjectRest
|
||||
&& !(element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
|
||||
&& !(getTargetOfEffectiveBindingElement(element).transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))) {
|
||||
&& !(getTargetOfBindingOrAssignmentElement(element).transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))) {
|
||||
bindingElements = append(bindingElements, element);
|
||||
}
|
||||
else {
|
||||
@ -315,9 +253,9 @@ namespace ts {
|
||||
host.emitBindingOrAssignment(host.createObjectBindingOrAssignmentPattern(bindingElements), boundValue, location, bindingTarget);
|
||||
bindingElements = undefined;
|
||||
}
|
||||
const propertyName = getEffectivePropertyNameOfEffectiveBindingElement(element);
|
||||
const propertyName = getPropertyNameOfBindingOrAssignmentElement(element);
|
||||
const value = createDestructuringPropertyAccess(host, boundValue, propertyName);
|
||||
flattenEffectiveBindingElement(host, element, value, /*location*/ element);
|
||||
flattenBindingOrAssignmentElement(host, element, value, /*location*/ element);
|
||||
}
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
@ -326,7 +264,7 @@ namespace ts {
|
||||
bindingElements = undefined;
|
||||
}
|
||||
const value = createRestCall(boundValue, elements, bindingTarget);
|
||||
flattenEffectiveBindingElement(host, element, value, element);
|
||||
flattenBindingOrAssignmentElement(host, element, value, element);
|
||||
}
|
||||
}
|
||||
if (bindingElements) {
|
||||
@ -334,16 +272,27 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function flattenEffectiveArrayBindingElements(host: FlattenHost, bindingTarget: EffectiveArrayBindingOrAssignmentPattern, elements: EffectiveBindingOrAssignmentElement[], boundValue: Expression, location: TextRange) {
|
||||
let bindingElements: EffectiveBindingOrAssignmentElement[];
|
||||
let spreadContainingElements: [Identifier, EffectiveBindingOrAssignmentElement][];
|
||||
function flattenArrayBindingOrAssignmentPattern(host: FlattenHost, parentElement: BindingOrAssignmentElement, bindingTarget: ArrayBindingOrAssignmentPattern, boundValue: Expression, location: TextRange) {
|
||||
const elements = getElementsOfBindingOrAssignmentPattern(bindingTarget);
|
||||
const numElements = elements.length;
|
||||
if (numElements !== 1 && (host.level < FlattenLevel.ObjectRest || numElements === 0)) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(parentElement) || numElements !== 0;
|
||||
boundValue = ensureIdentifier(host, boundValue, reuseIdentifierExpressions, location);
|
||||
}
|
||||
let bindingElements: BindingOrAssignmentElement[];
|
||||
let restContainingElements: [Identifier, BindingOrAssignmentElement][];
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (host.level <= FlattenLevel.ObjectRest) {
|
||||
if (element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest) && i < numElements - 1) {
|
||||
if (host.level >= FlattenLevel.ObjectRest) {
|
||||
// If an array pattern contains an ObjectRest, we must cache the result so that we
|
||||
// can perform the ObjectRest destructuring in a different declaration
|
||||
if (element.transformFlags & TransformFlags.ContainsObjectRest) {
|
||||
const temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
spreadContainingElements = append(spreadContainingElements, <[Identifier, EffectiveBindingOrAssignmentElement]>[temp, element]);
|
||||
restContainingElements = append(restContainingElements, <[Identifier, BindingOrAssignmentElement]>[temp, element]);
|
||||
bindingElements = append(bindingElements, host.createArrayBindingOrAssignmentElement(temp));
|
||||
}
|
||||
else {
|
||||
@ -353,21 +302,21 @@ namespace ts {
|
||||
else if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
else if (!getEffectiveRestIndicator(element)) {
|
||||
else if (!getRestIndicatorOfBindingOrAssignmentElement(element)) {
|
||||
const value = createElementAccess(boundValue, i);
|
||||
flattenEffectiveBindingElement(host, element, value, /*location*/ element);
|
||||
flattenBindingOrAssignmentElement(host, element, value, /*location*/ element);
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
const value = createArraySlice(boundValue, i);
|
||||
flattenEffectiveBindingElement(host, element, value, /*location*/ element);
|
||||
flattenBindingOrAssignmentElement(host, element, value, /*location*/ element);
|
||||
}
|
||||
}
|
||||
if (bindingElements) {
|
||||
host.emitBindingOrAssignment(host.createArrayBindingOrAssignmentPattern(bindingElements), boundValue, location, bindingTarget);
|
||||
}
|
||||
if (spreadContainingElements) {
|
||||
for (const [id, element] of spreadContainingElements) {
|
||||
flattenEffectiveBindingElement(host, element, id, element);
|
||||
if (restContainingElements) {
|
||||
for (const [id, element] of restContainingElements) {
|
||||
flattenBindingOrAssignmentElement(host, element, id, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -448,321 +397,35 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the EffectiveBindingElement is a declaration
|
||||
*/
|
||||
function isDeclarationBindingElement(bindingElement: EffectiveBindingOrAssignmentElement): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initializer of an EffectiveBindingElement.
|
||||
*/
|
||||
function getInitializerOfEffectiveBindingElement(bindingElement: EffectiveBindingOrAssignmentElement): Expression | undefined {
|
||||
if (isDeclarationBindingElement(bindingElement)) {
|
||||
// `1` in `let { a = 1 } = ...`
|
||||
// `1` in `let { a: b = 1 } = ...`
|
||||
// `1` in `let { a: {b} = 1 } = ...`
|
||||
// `1` in `let { a: [b] = 1 } = ...`
|
||||
// `1` in `let [a = 1] = ...`
|
||||
// `1` in `let [{a} = 1] = ...`
|
||||
// `1` in `let [[a] = 1] = ...`
|
||||
return bindingElement.initializer;
|
||||
}
|
||||
|
||||
if (isPropertyAssignment(bindingElement)) {
|
||||
// `1` in `({ a: b = 1 } = ...)`
|
||||
// `1` in `({ a: {b} = 1 } = ...)`
|
||||
// `1` in `({ a: [b] = 1 } = ...)`
|
||||
return isAssignmentExpression(bindingElement.initializer, /*excludeCompoundAssignment*/ true)
|
||||
? bindingElement.initializer.right
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (isShorthandPropertyAssignment(bindingElement)) {
|
||||
// `1` in `({ a = 1 } = ...)`
|
||||
return bindingElement.objectAssignmentInitializer;
|
||||
}
|
||||
|
||||
if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) {
|
||||
// `1` in `[a = 1] = ...`
|
||||
// `1` in `[{a} = 1] = ...`
|
||||
// `1` in `[[a] = 1] = ...`
|
||||
return bindingElement.right;
|
||||
}
|
||||
|
||||
if (isSpreadExpression(bindingElement) || isPartiallyEmittedExpression(bindingElement)) {
|
||||
// Recovery consistent with existing emit.
|
||||
return getInitializerOfEffectiveBindingElement(bindingElement.expression);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of an EffectiveBindingElement.
|
||||
*/
|
||||
function getTargetOfEffectiveBindingElement(bindingElement: EffectiveBindingOrAssignmentElement): EffectiveBindingOrAssignmentTarget {
|
||||
if (isDeclarationBindingElement(bindingElement)) {
|
||||
// `a` in `let { a } = ...`
|
||||
// `a` in `let { a = 1 } = ...`
|
||||
// `b` in `let { a: b } = ...`
|
||||
// `b` in `let { a: b = 1 } = ...`
|
||||
// `a` in `let { ...a } = ...`
|
||||
// `{b}` in `let { a: {b} } = ...`
|
||||
// `{b}` in `let { a: {b} = 1 } = ...`
|
||||
// `[b]` in `let { a: [b] } = ...`
|
||||
// `[b]` in `let { a: [b] = 1 } = ...`
|
||||
// `a` in `let [a] = ...`
|
||||
// `a` in `let [a = 1] = ...`
|
||||
// `a` in `let [...a] = ...`
|
||||
// `{a}` in `let [{a}] = ...`
|
||||
// `{a}` in `let [{a} = 1] = ...`
|
||||
// `[a]` in `let [[a]] = ...`
|
||||
// `[a]` in `let [[a] = 1] = ...`
|
||||
return <ObjectBindingPattern | ArrayBindingPattern | Identifier>bindingElement.name;
|
||||
}
|
||||
|
||||
if (isObjectLiteralElementLike(bindingElement)) {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
// `b` in `({ a: b } = ...)`
|
||||
// `b` in `({ a: b = 1 } = ...)`
|
||||
// `{b}` in `({ a: {b} } = ...)`
|
||||
// `{b}` in `({ a: {b} = 1 } = ...)`
|
||||
// `[b]` in `({ a: [b] } = ...)`
|
||||
// `[b]` in `({ a: [b] = 1 } = ...)`
|
||||
// `b.c` in `({ a: b.c } = ...)`
|
||||
// `b.c` in `({ a: b.c = 1 } = ...)`
|
||||
// `b[0]` in `({ a: b[0] } = ...)`
|
||||
// `b[0]` in `({ a: b[0] = 1 } = ...)`
|
||||
return getTargetOfEffectiveBindingElement(bindingElement.initializer);
|
||||
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
// `a` in `({ a } = ...)`
|
||||
// `a` in `({ a = 1 } = ...)`
|
||||
return bindingElement.name;
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
// `a` in `({ ...a } = ...)`
|
||||
return getTargetOfEffectiveBindingElement(bindingElement.expression);
|
||||
}
|
||||
|
||||
// no target
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) {
|
||||
// `a` in `[a = 1] = ...`
|
||||
// `{a}` in `[{a} = 1] = ...`
|
||||
// `[a]` in `[[a] = 1] = ...`
|
||||
// `a.b` in `[a.b = 1] = ...`
|
||||
// `a[0]` in `[a[0] = 1] = ...`
|
||||
return getTargetOfEffectiveBindingElement(bindingElement.left);
|
||||
}
|
||||
|
||||
if (isSpreadExpression(bindingElement) || isPartiallyEmittedExpression(bindingElement)) {
|
||||
// `a` in `[...a] = ...`
|
||||
return getTargetOfEffectiveBindingElement(bindingElement.expression);
|
||||
}
|
||||
|
||||
// `a` in `[a] = ...`
|
||||
// `{a}` in `[{a}] = ...`
|
||||
// `[a]` in `[[a]] = ...`
|
||||
// `a.b` in `[a.b] = ...`
|
||||
// `a[0]` in `[a[0]] = ...`
|
||||
return bindingElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an EffectiveBindingElement is a rest element.
|
||||
*/
|
||||
function getEffectiveRestIndicator(bindingElement: EffectiveBindingOrAssignmentElement): EffectiveBindingOrAssignmentRestIndicator {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
// `...` in `let [...a] = ...`
|
||||
return (<ParameterDeclaration | BindingElement>bindingElement).dotDotDotToken;
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
// `...` in `[...a] = ...`
|
||||
return <SpreadElement | SpreadAssignment>bindingElement;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property name of a BindingElement-like element
|
||||
*/
|
||||
function getEffectivePropertyNameOfEffectiveBindingElement(bindingElement: EffectiveBindingOrAssignmentElement) {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.BindingElement:
|
||||
// `a` in `let { a: b } = ...`
|
||||
// `[a]` in `let { [a]: b } = ...`
|
||||
// `"a"` in `let { "a": b } = ...`
|
||||
// `1` in `let { 1: b } = ...`
|
||||
if ((<BindingElement>bindingElement).propertyName) {
|
||||
return (<BindingElement>bindingElement).propertyName;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
// `a` in `({ a: b } = ...)`
|
||||
// `[a]` in `({ [a]: b } = ...)`
|
||||
// `"a"` in `({ "a": b } = ...)`
|
||||
// `1` in `({ 1: b } = ...)`
|
||||
if ((<PropertyAssignment>bindingElement).name) {
|
||||
return (<PropertyAssignment>bindingElement).name;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
// `a` in `({ ...a } = ...)`
|
||||
return (<SpreadAssignment>bindingElement).name;
|
||||
}
|
||||
|
||||
const target = getTargetOfEffectiveBindingElement(bindingElement);
|
||||
if (target && isPropertyName(target)) {
|
||||
return target;
|
||||
}
|
||||
|
||||
Debug.fail("Invalid property name for binding element.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is BindingPattern-like
|
||||
*/
|
||||
function isEffectiveBindingPattern(node: EffectiveBindingOrAssignmentTarget): node is EffectiveBindingOrAssignmentPattern {
|
||||
return isEffectiveObjectBindingPattern(node)
|
||||
|| isEffectiveArrayBindingPattern(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is ObjectBindingPattern-like
|
||||
*/
|
||||
function isEffectiveObjectBindingPattern(node: EffectiveBindingOrAssignmentTarget): node is EffectiveObjectBindingOrAssignmentPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is ArrayBindingPattern-like
|
||||
*/
|
||||
function isEffectiveArrayBindingPattern(node: EffectiveBindingOrAssignmentTarget): node is EffectiveArrayBindingOrAssignmentPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the elements of a BindingPattern-like name
|
||||
*/
|
||||
function getElementsOfEffectiveBindingPattern(name: EffectiveBindingOrAssignmentPattern): EffectiveBindingOrAssignmentElement[] {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
// `a` in `{a}`
|
||||
// `a` in `[a]`
|
||||
return name.elements;
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
// `a` in `{a}`
|
||||
return name.properties;
|
||||
}
|
||||
}
|
||||
|
||||
function createEffectiveArrayBindingPattern(elements: EffectiveBindingOrAssignmentElement[]) {
|
||||
function makeArrayBindingPattern(elements: BindingOrAssignmentElement[]) {
|
||||
Debug.assertEachNode(elements, isArrayBindingElement);
|
||||
return createArrayBindingPattern(<ArrayBindingElement[]>elements);
|
||||
}
|
||||
|
||||
function createEffectiveArrayAssignmentPattern(elements: EffectiveBindingOrAssignmentElement[]) {
|
||||
return createArrayLiteral(map(elements, convertToArrayLiteralElement));
|
||||
function makeArrayAssignmentPattern(elements: BindingOrAssignmentElement[]) {
|
||||
return createArrayLiteral(map(elements, convertToArrayAssignmentElement));
|
||||
}
|
||||
|
||||
function createEffectiveObjectBindingPattern(elements: EffectiveBindingOrAssignmentElement[]) {
|
||||
function makeObjectBindingPattern(elements: BindingOrAssignmentElement[]) {
|
||||
Debug.assertEachNode(elements, isBindingElement);
|
||||
return createObjectBindingPattern(<BindingElement[]>elements);
|
||||
}
|
||||
|
||||
function createEffectiveObjectAssignmentPattern(elements: EffectiveBindingOrAssignmentElement[]) {
|
||||
return createObjectLiteral(map(elements, convertToObjectLiteralElement));
|
||||
function makeObjectAssignmentPattern(elements: BindingOrAssignmentElement[]) {
|
||||
return createObjectLiteral(map(elements, convertToObjectAssignmentElement));
|
||||
}
|
||||
|
||||
function createEffectiveBindingElement(name: Identifier) {
|
||||
function makeBindingElement(name: Identifier) {
|
||||
return createBindingElement(/*propertyName*/ undefined, /*dotDotDotToken*/ undefined, name);
|
||||
}
|
||||
|
||||
function createEffectiveAssignmentElement(name: Identifier) {
|
||||
function makeAssignmentElement(name: Identifier) {
|
||||
return name;
|
||||
}
|
||||
|
||||
function convertToArrayLiteralElement(element: EffectiveBindingOrAssignmentElement) {
|
||||
if (isBindingElement(element)) {
|
||||
if (element.dotDotDotToken) {
|
||||
Debug.assertNode(element.name, isIdentifier);
|
||||
return setOriginalNode(createSpread(<Identifier>element.name, element), element);
|
||||
}
|
||||
const expression = convertToExpressionTarget(<ObjectBindingPattern | ArrayBindingPattern | Identifier>element.name);
|
||||
return element.initializer ? setOriginalNode(createAssignment(expression, element.initializer, element), element) : expression;
|
||||
}
|
||||
Debug.assertNode(element, isExpression);
|
||||
return <Expression>element;
|
||||
}
|
||||
|
||||
function convertToObjectLiteralElement(element: EffectiveBindingOrAssignmentElement) {
|
||||
if (isBindingElement(element)) {
|
||||
if (element.dotDotDotToken) {
|
||||
Debug.assertNode(element.name, isIdentifier);
|
||||
return setOriginalNode(createSpreadAssignment(<Identifier>element.name, element), element);
|
||||
}
|
||||
if (element.propertyName) {
|
||||
const expression = convertToExpressionTarget(<ObjectBindingPattern | ArrayBindingPattern | Identifier>element.name);
|
||||
return setOriginalNode(createPropertyAssignment(element.propertyName, element.initializer ? createAssignment(expression, element.initializer) : expression, element), element);
|
||||
}
|
||||
Debug.assertNode(element.name, isIdentifier);
|
||||
return setOriginalNode(createShorthandPropertyAssignment(<Identifier>element.name, element.initializer, element), element);
|
||||
}
|
||||
Debug.assertNode(element, isObjectLiteralElementLike);
|
||||
return <ObjectLiteralElementLike>element;
|
||||
}
|
||||
|
||||
function convertToExpressionTarget(target: EffectiveBindingOrAssignmentTarget): Expression {
|
||||
if (isBindingPattern(target)) {
|
||||
switch (target.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return setOriginalNode(createArrayLiteral(map(target.elements, convertToArrayLiteralElement), target), target);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return setOriginalNode(createObjectLiteral(map(target.elements, convertToObjectLiteralElement), target), target);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Debug.assertNode(target, isExpression);
|
||||
return <Expression>target;
|
||||
}
|
||||
|
||||
/** 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(value: Expression, elements: EffectiveBindingOrAssignmentElement[], location: TextRange): Expression {
|
||||
function createRestCall(value: Expression, elements: BindingOrAssignmentElement[], location: TextRange): Expression {
|
||||
const propertyNames: LiteralExpression[] = [];
|
||||
for (let i = 0; i < elements.length - 1; i++) {
|
||||
if (isOmittedExpression(elements[i])) {
|
||||
@ -771,7 +434,7 @@ namespace ts {
|
||||
const str = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
|
||||
str.pos = location.pos;
|
||||
str.end = location.end;
|
||||
str.text = getTextOfPropertyName(getEffectivePropertyNameOfEffectiveBindingElement(elements[i]));
|
||||
str.text = getTextOfPropertyName(getPropertyNameOfBindingOrAssignmentElement(elements[i]));
|
||||
propertyNames.push(str);
|
||||
}
|
||||
const args = createSynthesizedNodeArray([value, createArrayLiteral(propertyNames, location)]);
|
||||
|
||||
@ -1365,7 +1365,7 @@ namespace ts {
|
||||
function visitBinaryExpression(node: BinaryExpression, needsDestructuringValue: boolean): Expression {
|
||||
// If we are here it is because this is a destructuring assignment.
|
||||
Debug.assert(isDestructuringAssignment(node));
|
||||
return flattenDestructuringToExpression(
|
||||
return flattenDestructuringAssignment(
|
||||
context,
|
||||
<DestructuringAssignment>node,
|
||||
needsDestructuringValue,
|
||||
@ -1383,7 +1383,7 @@ namespace ts {
|
||||
if (decl.initializer) {
|
||||
let assignment: Expression;
|
||||
if (isBindingPattern(decl.name)) {
|
||||
assignment = flattenDestructuringToExpression(
|
||||
assignment = flattenDestructuringAssignment(
|
||||
context,
|
||||
decl,
|
||||
/*needsValue*/ false,
|
||||
@ -1543,8 +1543,7 @@ namespace ts {
|
||||
if (isBindingPattern(node.name)) {
|
||||
const recordTempVariablesInLine = !enclosingVariableStatement
|
||||
|| !hasModifier(enclosingVariableStatement, ModifierFlags.Export);
|
||||
debugger;
|
||||
return flattenDestructuringToDeclarations(
|
||||
return flattenDestructuringBinding(
|
||||
context,
|
||||
node,
|
||||
/*value*/ undefined,
|
||||
@ -2181,7 +2180,7 @@ namespace ts {
|
||||
const temp = createTempVariable(undefined);
|
||||
const newVariableDeclaration = createVariableDeclaration(temp, undefined, undefined, node.variableDeclaration);
|
||||
|
||||
const vars = flattenDestructuringToDeclarations(context, node.variableDeclaration, temp, /*skipInitializer*/ false, /*recordTempVariablesInLine*/ true, FlattenLevel.All, visitor);
|
||||
const vars = flattenDestructuringBinding(context, node.variableDeclaration, temp, /*skipInitializer*/ false, /*recordTempVariablesInLine*/ true, FlattenLevel.All, visitor);
|
||||
const list = createVariableDeclarationList(vars, /*location*/node.variableDeclaration, /*flags*/node.variableDeclaration.flags);
|
||||
const destructure = createVariableStatement(undefined, list);
|
||||
|
||||
|
||||
@ -135,7 +135,7 @@ namespace ts {
|
||||
*/
|
||||
function visitBinaryExpression(node: BinaryExpression, needsDestructuringValue: boolean): Expression {
|
||||
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsESNext) {
|
||||
return flattenDestructuringToExpression(
|
||||
return flattenDestructuringAssignment(
|
||||
context,
|
||||
node,
|
||||
needsDestructuringValue,
|
||||
@ -156,7 +156,7 @@ namespace ts {
|
||||
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) {
|
||||
return flattenDestructuringToDeclarations(context, node, /*boundValue*/ undefined, /*skipInitializer*/ false, /*recordTempVariablesInLine*/ true, FlattenLevel.ObjectRest, visitor);
|
||||
return flattenDestructuringBinding(context, node, /*boundValue*/ undefined, /*skipInitializer*/ false, /*recordTempVariablesInLine*/ true, FlattenLevel.ObjectRest, visitor);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@ -202,14 +202,14 @@ namespace ts {
|
||||
const declaration = firstOrUndefined(initializer.declarations);
|
||||
return declaration && declaration.name &&
|
||||
declaration.name.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
!!(declaration.name.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest));
|
||||
!!(declaration.name.transformFlags & TransformFlags.ContainsObjectRest);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRestAssignment(initializer: ForInitializer) {
|
||||
return initializer.kind === SyntaxKind.ObjectLiteralExpression &&
|
||||
initializer.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest);
|
||||
initializer.transformFlags & TransformFlags.ContainsObjectRest;
|
||||
}
|
||||
|
||||
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
|
||||
@ -238,7 +238,7 @@ namespace ts {
|
||||
function isObjectRestParameter(node: ParameterDeclaration) {
|
||||
return node.name &&
|
||||
node.name.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
!!(node.name.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest));
|
||||
!!(node.name.transformFlags & TransformFlags.ContainsObjectRest);
|
||||
}
|
||||
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): FunctionDeclaration {
|
||||
|
||||
@ -756,7 +756,7 @@ namespace ts {
|
||||
*/
|
||||
function transformInitializedVariable(node: VariableDeclaration): Expression {
|
||||
if (isBindingPattern(node.name)) {
|
||||
return flattenDestructuringToExpression(
|
||||
return flattenDestructuringAssignment(
|
||||
context,
|
||||
node,
|
||||
/*needsValue*/ false,
|
||||
|
||||
@ -808,7 +808,7 @@ namespace ts {
|
||||
function transformInitializedVariable(node: VariableDeclaration, isExportedDeclaration: boolean): Expression {
|
||||
const createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment;
|
||||
return isBindingPattern(node.name)
|
||||
? flattenDestructuringToExpression(context, node, /*needsValue*/ false, FlattenLevel.All, createAssignment, destructuringVisitor)
|
||||
? flattenDestructuringAssignment(context, node, /*needsValue*/ false, FlattenLevel.All, createAssignment, destructuringVisitor)
|
||||
: createAssignment(node.name, visitNode(node.initializer, destructuringVisitor, isExpression));
|
||||
}
|
||||
|
||||
@ -1459,7 +1459,7 @@ namespace ts {
|
||||
*/
|
||||
function visitDestructuringAssignment(node: DestructuringAssignment): VisitResult<Expression> {
|
||||
if (hasExportedReferenceInDestructuringTarget(node.left)) {
|
||||
return flattenDestructuringToExpression(
|
||||
return flattenDestructuringAssignment(
|
||||
context,
|
||||
node,
|
||||
/*needsValue*/ true,
|
||||
|
||||
@ -2353,7 +2353,7 @@ namespace ts {
|
||||
function transformInitializedVariable(node: VariableDeclaration): Expression {
|
||||
const name = node.name;
|
||||
if (isBindingPattern(name)) {
|
||||
return flattenDestructuringToExpression(
|
||||
return flattenDestructuringAssignment(
|
||||
context,
|
||||
node,
|
||||
/*needsValue*/ false,
|
||||
|
||||
@ -722,22 +722,20 @@ namespace ts {
|
||||
name: PropertyName;
|
||||
}
|
||||
|
||||
export interface BindingPattern extends Node {
|
||||
elements: NodeArray<BindingElement | ArrayBindingElement>;
|
||||
}
|
||||
|
||||
export interface ObjectBindingPattern extends BindingPattern {
|
||||
export interface ObjectBindingPattern extends Node {
|
||||
kind: SyntaxKind.ObjectBindingPattern;
|
||||
elements: NodeArray<BindingElement>;
|
||||
}
|
||||
|
||||
export type ArrayBindingElement = BindingElement | OmittedExpression;
|
||||
|
||||
export interface ArrayBindingPattern extends BindingPattern {
|
||||
export interface ArrayBindingPattern extends Node {
|
||||
kind: SyntaxKind.ArrayBindingPattern;
|
||||
elements: NodeArray<ArrayBindingElement>;
|
||||
}
|
||||
|
||||
export type BindingPattern = (ObjectBindingPattern | ArrayBindingPattern) & { elements: NodeArray<ArrayBindingElement>; };
|
||||
|
||||
export type ArrayBindingElement = BindingElement | OmittedExpression;
|
||||
|
||||
/**
|
||||
* Several node kinds share function-like features such as a signature,
|
||||
* a name, and a body. These nodes should extend FunctionLikeDeclaration.
|
||||
@ -1191,7 +1189,49 @@ namespace ts {
|
||||
left: ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
export type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment;
|
||||
export type DestructuringAssignment
|
||||
= ObjectDestructuringAssignment
|
||||
| ArrayDestructuringAssignment
|
||||
;
|
||||
|
||||
export type BindingOrAssignmentElement
|
||||
= VariableDeclaration
|
||||
| ParameterDeclaration
|
||||
| BindingElement
|
||||
| PropertyAssignment // AssignmentProperty
|
||||
| ShorthandPropertyAssignment // AssignmentProperty
|
||||
| SpreadAssignment // AssignmentRestProperty
|
||||
| OmittedExpression // Elision
|
||||
| SpreadElement // AssignmentRestElement
|
||||
| ArrayLiteralExpression // ArrayAssignmentPattern
|
||||
| ObjectLiteralExpression // ObjectAssignmentPattern
|
||||
| AssignmentExpression<EqualsToken> // AssignmentElement
|
||||
| Identifier // DestructuringAssignmentTarget
|
||||
| PropertyAccessExpression // DestructuringAssignmentTarget
|
||||
| ElementAccessExpression // DestructuringAssignmentTarget
|
||||
;
|
||||
|
||||
export type BindingOrAssignmentElementRestIndicator
|
||||
= DotDotDotToken // from BindingElement
|
||||
| SpreadElement // AssignmentRestElement
|
||||
| SpreadAssignment // AssignmentRestProperty
|
||||
;
|
||||
|
||||
export type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Expression;
|
||||
|
||||
export type ObjectBindingOrAssignmentPattern
|
||||
= ObjectBindingPattern
|
||||
| ObjectLiteralExpression // ObjectAssignmentPattern
|
||||
;
|
||||
|
||||
export type ArrayBindingOrAssignmentPattern
|
||||
= ArrayBindingPattern
|
||||
| ArrayLiteralExpression // ArrayAssignmentPattern
|
||||
;
|
||||
|
||||
export type AssignmentPattern = ObjectLiteralExpression | ArrayLiteralExpression;
|
||||
|
||||
export type BindingOrAssignmentPattern = ObjectBindingOrAssignmentPattern | ArrayBindingOrAssignmentPattern;
|
||||
|
||||
export interface ConditionalExpression extends Expression {
|
||||
kind: SyntaxKind.ConditionalExpression;
|
||||
@ -3554,10 +3594,10 @@ namespace ts {
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectSpread,
|
||||
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpread,
|
||||
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectSpread,
|
||||
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRest,
|
||||
ParameterExcludes = NodeExcludes,
|
||||
CatchClauseExcludes = NodeExcludes | ContainsObjectSpread,
|
||||
BindingPatternExcludes = NodeExcludes | ContainsSpread,
|
||||
CatchClauseExcludes = NodeExcludes | ContainsObjectRest,
|
||||
BindingPatternExcludes = NodeExcludes | ContainsRest,
|
||||
|
||||
// Masks
|
||||
// - Additional bitmasks
|
||||
|
||||
@ -3948,6 +3948,78 @@ namespace ts {
|
||||
|| kind === SyntaxKind.OmittedExpression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the BindingOrAssignmentElement is a BindingElement-like declaration
|
||||
*/
|
||||
export function isDeclarationBindingElement(bindingElement: BindingOrAssignmentElement): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a BindingOrAssignmentElement
|
||||
*/
|
||||
export function isBindingOrAssignmentElement(node: Node): node is BindingOrAssignmentElement {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
case SyntaxKind.OmittedExpression:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.SpreadElement:
|
||||
return true;
|
||||
}
|
||||
return isAssignmentExpression(node, /*excludeCompoundAssignment*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a BindingOrAssignmentPattern
|
||||
*/
|
||||
export function isBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is BindingOrAssignmentPattern {
|
||||
return isObjectBindingOrAssignmentPattern(node)
|
||||
|| isArrayBindingOrAssignmentPattern(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is an ObjectBindingOrAssignmentPattern
|
||||
*/
|
||||
export function isObjectBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ObjectBindingOrAssignmentPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is an ArrayBindingOrAssignmentPattern
|
||||
*/
|
||||
export function isArrayBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ArrayBindingOrAssignmentPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Expression
|
||||
|
||||
export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user