mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-17 01:55:50 -06:00
Clean up and consolidate destructuring transform
This commit is contained in:
parent
6453fde400
commit
86091d7217
@ -1007,7 +1007,7 @@ namespace ts {
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
bind(node.finallyBlock);
|
||||
// if flow after finally is unreachable - keep it
|
||||
// otherwise check if flows after try and after catch are unreachable
|
||||
// otherwise check if flows after try and after catch are unreachable
|
||||
// if yes - convert current flow to unreachable
|
||||
// i.e.
|
||||
// try { return "1" } finally { console.log(1); }
|
||||
@ -3077,7 +3077,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
// This node is ES6 syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadElementExpression;
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsSpreadElementExpression;
|
||||
break;
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
|
||||
@ -2025,9 +2025,7 @@ namespace ts {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = indentation ? lines[i].slice(indentation) : lines[i];
|
||||
if (line.length) {
|
||||
if (i > 0) {
|
||||
writeLine();
|
||||
}
|
||||
writeLine();
|
||||
write(line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1699,6 +1699,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
export interface CallBinding {
|
||||
target: LeftHandSideExpression;
|
||||
thisArg: Expression;
|
||||
@ -2733,7 +2735,9 @@ namespace ts {
|
||||
*/
|
||||
export function addEmitHelper<T extends Node>(node: T, helper: EmitHelper): T {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
emitNode.helpers = append(emitNode.helpers, helper);
|
||||
if (!contains(emitNode.helpers, helper)) {
|
||||
emitNode.helpers = append(emitNode.helpers, helper);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@ -3,137 +3,146 @@
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
type EffectiveBindingElement
|
||||
= VariableDeclaration
|
||||
| ParameterDeclaration
|
||||
| BindingElement
|
||||
| ObjectLiteralElementLike
|
||||
| Expression
|
||||
;
|
||||
|
||||
type EffectiveObjectBindingPattern
|
||||
= ObjectBindingPattern
|
||||
| ObjectLiteralExpression
|
||||
;
|
||||
|
||||
type EffectiveArrayBindingPattern
|
||||
= ArrayBindingPattern
|
||||
| ArrayLiteralExpression
|
||||
;
|
||||
|
||||
type EffectiveBindingPattern
|
||||
= EffectiveObjectBindingPattern
|
||||
| EffectiveArrayBindingPattern
|
||||
;
|
||||
|
||||
type EffectiveBindingTarget
|
||||
= EffectiveBindingPattern
|
||||
| Expression
|
||||
;
|
||||
|
||||
/**
|
||||
* Flattens a destructuring assignment expression.
|
||||
* Flattens a DestructuringAssignment or a VariableDeclaration to an expression.
|
||||
*
|
||||
* @param root The destructuring assignment expression.
|
||||
* @param node The node to flatten.
|
||||
* @param needsValue Indicates whether the value from the right-hand-side of the
|
||||
* destructuring assignment is needed as part of a larger expression.
|
||||
* destructuring assignment is needed as part of a larger expression.
|
||||
* @param createAssignmentCallback A callback used to create an assignment expression.
|
||||
* @param recordTempVariable A callback used to record new temporary variables.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
* @param visitor An optional visitor used to visit default value initializers of binding patterns.
|
||||
*/
|
||||
export function flattenDestructuringAssignment(
|
||||
context: TransformationContext,
|
||||
node: BinaryExpression,
|
||||
export function flattenDestructuringToExpression(
|
||||
node: VariableDeclaration | DestructuringAssignment,
|
||||
needsValue: boolean,
|
||||
createAssignmentCallback: (target: Expression, value: Expression, location?: TextRange) => Expression,
|
||||
recordTempVariable: (node: Identifier) => void,
|
||||
visitor?: (node: Node) => VisitResult<Node>): Expression {
|
||||
|
||||
if (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
const right = node.right;
|
||||
if (isDestructuringAssignment(right)) {
|
||||
return flattenDestructuringAssignment(context, right, needsValue, recordTempVariable, visitor);
|
||||
}
|
||||
else {
|
||||
return node.right;
|
||||
}
|
||||
}
|
||||
|
||||
let location: TextRange = node;
|
||||
let value = node.right;
|
||||
let value: Expression;
|
||||
if (isDestructuringAssignment(node)) {
|
||||
value = node.right;
|
||||
while (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
if (isDestructuringAssignment(value)) {
|
||||
location = node = value;
|
||||
value = node.right;
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expressions: Expression[] = [];
|
||||
if (needsValue) {
|
||||
// If the right-hand value of the destructuring assignment needs to be preserved (as
|
||||
// is the case when the destructuring assignmen) is part of a larger expression),
|
||||
// then we need to cache the right-hand value.
|
||||
//
|
||||
// The source map location for the assignment should point to the entire binary
|
||||
// expression.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment, visitor);
|
||||
}
|
||||
else if (nodeIsSynthesized(node)) {
|
||||
// Generally, the source map location for a destructuring assignment is the root
|
||||
// expression.
|
||||
//
|
||||
// However, if the root expression is synthesized (as in the case
|
||||
// of the initializer when transforming a ForOfStatement), then the source map
|
||||
// location should point to the right-hand value of the expression.
|
||||
location = value;
|
||||
|
||||
if (value) {
|
||||
value = visitNode(value, visitor, isExpression);
|
||||
if (needsValue) {
|
||||
// If the right-hand value of the destructuring assignment needs to be preserved (as
|
||||
// is the case when the destructuring assignment is part of a larger expression),
|
||||
// then we need to cache the right-hand value.
|
||||
//
|
||||
// The source map location for the assignment should point to the entire binary
|
||||
// expression.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, emitTempVariableAssignment, location);
|
||||
}
|
||||
else if (nodeIsSynthesized(node)) {
|
||||
// Generally, the source map location for a destructuring assignment is the root
|
||||
// expression.
|
||||
//
|
||||
// However, if the root expression is synthesized (as in the case
|
||||
// of the initializer when transforming a ForOfStatement), then the source map
|
||||
// location should point to the right-hand value of the expression.
|
||||
location = value;
|
||||
}
|
||||
}
|
||||
|
||||
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
flattenEffectiveBindingElement(node, value, isDestructuringAssignment(node), emitAssignment, emitTempVariableAssignment, visitor, location);
|
||||
|
||||
if (needsValue) {
|
||||
if (value && needsValue) {
|
||||
expressions.push(value);
|
||||
}
|
||||
|
||||
const expression = inlineExpressions(expressions);
|
||||
aggregateTransformFlags(expression);
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
return aggregateTransformFlags(inlineExpressions(expressions));
|
||||
|
||||
function emitAssignment(target: Expression, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignmentCallback(target, value, location);
|
||||
expression.original = original;
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
// `emitAssignment` in the old emitter.
|
||||
setEmitFlags(expression, EmitFlags.NoNestedSourceMaps);
|
||||
|
||||
aggregateTransformFlags(expression);
|
||||
expressions.push(expression);
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable(recordTempVariable);
|
||||
emitAssignment(name, value, location);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens binding patterns in a parameter declaration.
|
||||
*
|
||||
* @param node The ParameterDeclaration to flatten.
|
||||
* @param value The rhs value for the binding pattern.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenParameterDestructuring(
|
||||
node: ParameterDeclaration,
|
||||
value: Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
return declarations;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
const declaration = createVariableDeclaration(name, /*type*/ undefined, value, location);
|
||||
|
||||
const expression = createAssignment(name, value, location);
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
// `emitAssignment` in the old emitter.
|
||||
setEmitFlags(declaration, EmitFlags.NoNestedSourceMaps);
|
||||
|
||||
aggregateTransformFlags(declaration);
|
||||
declarations.push(declaration);
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
emitAssignment(name, value, location);
|
||||
setEmitFlags(expression, EmitFlags.NoNestedSourceMaps);
|
||||
aggregateTransformFlags(expression);
|
||||
expressions.push(expression);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens binding patterns in a variable declaration.
|
||||
* Flattens binding patterns in a VariableDeclaration or a ParameterDeclaration to a VariableDeclaration list.
|
||||
*
|
||||
* @param node The VariableDeclaration to flatten.
|
||||
* @param value An optional rhs value for the binding pattern.
|
||||
* @param node The node to flatten.
|
||||
* @param boundValue An optional rhs value for the binding pattern. This value is *not* visited during flattening.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
* @param recordTempVariable An optional callback used to hoist temporary variables rather than
|
||||
* declaring them inline.
|
||||
*/
|
||||
export function flattenVariableDestructuring(
|
||||
node: VariableDeclaration,
|
||||
value?: Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>,
|
||||
recordTempVariable?: (node: Identifier) => void) {
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
export function flattenDestructuring(
|
||||
node: VariableDeclaration | ParameterDeclaration,
|
||||
boundValue?: Expression,
|
||||
recordTempVariable?: (node: Identifier) => void,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
|
||||
let pendingAssignments: Expression[];
|
||||
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
const declarations: VariableDeclaration[] = [];
|
||||
flattenEffectiveBindingElement(node, boundValue, /*skipInitializer*/ false, emitAssignment, emitTempVariableAssignment, visitor, /*location*/ node);
|
||||
return declarations;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
function emitAssignment(name: Expression, value: Expression, location: TextRange, original: Node) {
|
||||
if (!isIdentifier(name)) {
|
||||
Debug.failBadSyntaxKind(name, "Identifier expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingAssignments) {
|
||||
pendingAssignments.push(value);
|
||||
value = inlineExpressions(pendingAssignments);
|
||||
@ -145,22 +154,13 @@ namespace ts {
|
||||
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
// `emitAssignment` in the old emitter.
|
||||
setEmitFlags(declaration, EmitFlags.NoNestedSourceMaps);
|
||||
|
||||
declarations.push(declaration);
|
||||
aggregateTransformFlags(declaration);
|
||||
declarations.push(aggregateTransformFlags(setEmitFlags(declaration, EmitFlags.NoNestedSourceMaps)));
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable(recordTempVariable);
|
||||
if (recordTempVariable) {
|
||||
const assignment = createAssignment(name, value, location);
|
||||
if (pendingAssignments) {
|
||||
pendingAssignments.push(assignment);
|
||||
}
|
||||
else {
|
||||
pendingAssignments = [assignment];
|
||||
}
|
||||
pendingAssignments = append(pendingAssignments, createAssignment(name, value, location));
|
||||
}
|
||||
else {
|
||||
emitAssignment(name, value, location, /*original*/ undefined);
|
||||
@ -169,244 +169,365 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function flattenEffectiveBindingElement(
|
||||
bindingElement: EffectiveBindingElement,
|
||||
boundValue: Expression | undefined,
|
||||
skipInitializer: boolean,
|
||||
emitAssignment: (target: Expression, value: Expression, location: TextRange, original: Node) => void,
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
|
||||
visitor: ((node: Node) => VisitResult<Node>) | undefined,
|
||||
location: TextRange) {
|
||||
|
||||
if (!skipInitializer) {
|
||||
const initializer = visitNode(getInitializerOfEffectiveBindingElement(bindingElement), visitor, isExpression);
|
||||
if (initializer) {
|
||||
// Combine value and initializer
|
||||
boundValue = boundValue ? createDefaultValueCheck(boundValue, initializer, location, emitTempVariableAssignment) : initializer;
|
||||
}
|
||||
else if (!boundValue) {
|
||||
// Use 'void 0' in absence of value and initializer
|
||||
boundValue = createVoidZero();
|
||||
}
|
||||
}
|
||||
|
||||
const bindingTarget = getTargetOfEffectiveBindingElement(bindingElement);
|
||||
if (isEffectiveBindingPattern(bindingTarget)) {
|
||||
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(boundValue, reuseIdentifierExpressions, emitTempVariableAssignment, location);
|
||||
}
|
||||
|
||||
if (isEffectiveObjectBindingPattern(bindingTarget)) {
|
||||
for (const element of elements) {
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
flattenEffectiveBindingElement(
|
||||
element,
|
||||
createDestructuringPropertyAccess(
|
||||
boundValue,
|
||||
getEffectivePropertyNameOfEffectiveBindingElement(element),
|
||||
emitTempVariableAssignment),
|
||||
/*skipInitializer*/ false,
|
||||
emitAssignment,
|
||||
emitTempVariableAssignment,
|
||||
visitor,
|
||||
/*location*/ element);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (!isOmittedExpression(element)) {
|
||||
if (!isEffectiveBindingElementWithRest(element)) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
flattenEffectiveBindingElement(
|
||||
element,
|
||||
createElementAccess(boundValue, i),
|
||||
/*skipInitializer*/ false,
|
||||
emitAssignment,
|
||||
emitTempVariableAssignment,
|
||||
visitor,
|
||||
/*location*/ element);
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
flattenEffectiveBindingElement(
|
||||
element,
|
||||
createArraySlice(boundValue, i),
|
||||
/*skipInitializer*/ false,
|
||||
emitAssignment,
|
||||
emitTempVariableAssignment,
|
||||
visitor,
|
||||
/*location*/ element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitAssignment(bindingTarget, boundValue, location, /*original*/ bindingElement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens binding patterns in a variable declaration and transforms them into an expression.
|
||||
*
|
||||
* @param node The VariableDeclaration to flatten.
|
||||
* @param recordTempVariable A callback used to record new temporary variables.
|
||||
* @param createAssignmentCallback An optional callback used to create assignment expressions
|
||||
* for non-temporary variables.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
* Determines whether the BindingElement-like is a declaration
|
||||
*/
|
||||
export function flattenVariableDestructuringToExpression(
|
||||
node: VariableDeclaration,
|
||||
recordTempVariable: (name: Identifier) => void,
|
||||
createAssignmentCallback?: (name: Identifier, value: Expression, location?: TextRange) => Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
|
||||
const pendingAssignments: Expression[] = [];
|
||||
|
||||
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor);
|
||||
|
||||
const expression = inlineExpressions(pendingAssignments);
|
||||
aggregateTransformFlags(expression);
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignmentCallback
|
||||
? createAssignmentCallback(name, value, location)
|
||||
: createAssignment(name, value, location);
|
||||
|
||||
emitPendingAssignment(expression, original);
|
||||
function isDeclarationBindingElement(bindingElement: EffectiveBindingElement): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
return true;
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable(recordTempVariable);
|
||||
emitPendingAssignment(createAssignment(name, value, location), /*original*/ undefined);
|
||||
return name;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initializer of a BindingElement-like element
|
||||
*/
|
||||
function getInitializerOfEffectiveBindingElement(bindingElement: EffectiveBindingElement): 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;
|
||||
}
|
||||
|
||||
function emitPendingAssignment(expression: Expression, original: Node) {
|
||||
expression.original = original;
|
||||
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;
|
||||
}
|
||||
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
// `emitAssignment` in the old emitter.
|
||||
setEmitFlags(expression, EmitFlags.NoNestedSourceMaps);
|
||||
if (isShorthandPropertyAssignment(bindingElement)) {
|
||||
// `1` in `({ a = 1 } = ...)`
|
||||
return bindingElement.objectAssignmentInitializer;
|
||||
}
|
||||
|
||||
pendingAssignments.push(expression);
|
||||
if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) {
|
||||
// `1` in `[a = 1] = ...`
|
||||
// `1` in `[{a} = 1] = ...`
|
||||
// `1` in `[[a] = 1] = ...`
|
||||
return bindingElement.right;
|
||||
}
|
||||
|
||||
if (isSpreadElementExpression(bindingElement) || isPartiallyEmittedExpression(bindingElement)) {
|
||||
// Recovery consistent with existing emit.
|
||||
return getInitializerOfEffectiveBindingElement(bindingElement.expression);
|
||||
}
|
||||
}
|
||||
|
||||
function flattenDestructuring(
|
||||
root: VariableDeclaration | ParameterDeclaration | BindingElement | BinaryExpression,
|
||||
value: Expression,
|
||||
location: TextRange,
|
||||
emitAssignment: (name: Identifier, value: Expression, location: TextRange, original: Node) => void,
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
if (value && visitor) {
|
||||
value = visitNode(value, visitor, isExpression);
|
||||
/**
|
||||
* Gets the name of a BindingElement-like element
|
||||
*/
|
||||
function getTargetOfEffectiveBindingElement(bindingElement: EffectiveBindingElement): EffectiveBindingTarget {
|
||||
if (isDeclarationBindingElement(bindingElement)) {
|
||||
// `a` in `let { a } = ...`
|
||||
// `a` in `let { a = 1 } = ...`
|
||||
// `b` in `let { a: b } = ...`
|
||||
// `b` in `let { a: b = 1 } = ...`
|
||||
// `{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 (isBinaryExpression(root)) {
|
||||
emitDestructuringAssignment(root.left, value, location);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 (isSpreadElementExpression(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 a BindingElement-like element is a rest element.
|
||||
*/
|
||||
function isEffectiveBindingElementWithRest(bindingElement: EffectiveBindingElement) {
|
||||
switch (bindingElement.kind) {
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
// `...` in `let [...a] = ...`
|
||||
return (<ParameterDeclaration | BindingElement>bindingElement).dotDotDotToken !== undefined;
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
// `...` in `[...a] = ...`
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property name of a BindingElement-like element
|
||||
*/
|
||||
function getEffectivePropertyNameOfEffectiveBindingElement(bindingElement: EffectiveBindingElement) {
|
||||
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;
|
||||
}
|
||||
|
||||
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: EffectiveBindingTarget): node is EffectiveBindingPattern {
|
||||
return isEffectiveObjectBindingPattern(node)
|
||||
|| isEffectiveArrayBindingPattern(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is ObjectBindingPattern-like
|
||||
*/
|
||||
function isEffectiveObjectBindingPattern(node: EffectiveBindingTarget): node is EffectiveObjectBindingPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is ArrayBindingPattern-like
|
||||
*/
|
||||
function isEffectiveArrayBindingPattern(node: EffectiveBindingTarget): node is EffectiveArrayBindingPattern {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the elements of a BindingPattern-like name
|
||||
*/
|
||||
function getElementsOfEffectiveBindingPattern(name: EffectiveBindingPattern): EffectiveBindingElement[] {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
// `a` in `{a}`
|
||||
// `a` in `[a]`
|
||||
return name.elements;
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
// `a` in `{a}`
|
||||
return name.properties;
|
||||
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
// `a` in `[a]`
|
||||
return name.elements;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an expression used to provide a default value if a value is `undefined` at runtime.
|
||||
*/
|
||||
function createDefaultValueCheck(value: Expression, defaultValue: Expression, location: TextRange, emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier): Expression {
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, emitTempVariableAssignment, location);
|
||||
return createConditional(
|
||||
createStrictEquality(value, createVoidZero()),
|
||||
createToken(SyntaxKind.QuestionToken),
|
||||
defaultValue,
|
||||
createToken(SyntaxKind.ColonToken),
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates either a PropertyAccessExpression or an ElementAccessExpression for the
|
||||
* right-hand side of a transformed destructuring assignment.
|
||||
*
|
||||
* @param expression The right-hand expression that is the source of the property.
|
||||
* @param propertyName The destructuring property name.
|
||||
* @param emitTempVariableAssignment A callback used to emit a temporary variable.
|
||||
*/
|
||||
function createDestructuringPropertyAccess(expression: Expression, propertyName: PropertyName, emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier): LeftHandSideExpression {
|
||||
if (isComputedPropertyName(propertyName)) {
|
||||
const argumentExpression = ensureIdentifier(propertyName.expression, /*reuseIdentifierExpressions*/ false, emitTempVariableAssignment, /*location*/ propertyName);
|
||||
return createElementAccess(expression, argumentExpression);
|
||||
}
|
||||
else if (isLiteralExpression(propertyName)) {
|
||||
const argumentExpression = getSynthesizedClone(propertyName);
|
||||
argumentExpression.text = unescapeIdentifier(argumentExpression.text);
|
||||
return createElementAccess(expression, argumentExpression);
|
||||
}
|
||||
else if (isGeneratedIdentifier(propertyName)) {
|
||||
const name = getSynthesizedClone(propertyName);
|
||||
name.text = unescapeIdentifier(name.text);
|
||||
return createPropertyAccess(expression, name);
|
||||
}
|
||||
else {
|
||||
emitBindingElement(root, value);
|
||||
}
|
||||
|
||||
function emitDestructuringAssignment(bindingTarget: Expression | ShorthandPropertyAssignment, value: Expression, location: TextRange) {
|
||||
// When emitting target = value use source map node to highlight, including any temporary assignments needed for this
|
||||
let target: Expression;
|
||||
if (isShorthandPropertyAssignment(bindingTarget)) {
|
||||
const initializer = visitor
|
||||
? visitNode(bindingTarget.objectAssignmentInitializer, visitor, isExpression)
|
||||
: bindingTarget.objectAssignmentInitializer;
|
||||
|
||||
if (initializer) {
|
||||
value = createDefaultValueCheck(value, initializer, location);
|
||||
}
|
||||
|
||||
target = bindingTarget.name;
|
||||
}
|
||||
else if (isBinaryExpression(bindingTarget) && bindingTarget.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const initializer = visitor
|
||||
? visitNode(bindingTarget.right, visitor, isExpression)
|
||||
: bindingTarget.right;
|
||||
|
||||
value = createDefaultValueCheck(value, initializer, location);
|
||||
target = bindingTarget.left;
|
||||
}
|
||||
else {
|
||||
target = bindingTarget;
|
||||
}
|
||||
|
||||
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
emitObjectLiteralAssignment(<ObjectLiteralExpression>target, value, location);
|
||||
}
|
||||
else if (target.kind === SyntaxKind.ArrayLiteralExpression) {
|
||||
emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value, location);
|
||||
}
|
||||
else {
|
||||
const name = getMutableClone(<Identifier>target);
|
||||
setSourceMapRange(name, target);
|
||||
setCommentRange(name, target);
|
||||
emitAssignment(name, value, location, /*original*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression, location: TextRange) {
|
||||
const properties = target.properties;
|
||||
if (properties.length !== 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
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
}
|
||||
|
||||
for (const p of properties) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitArrayLiteralAssignment(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
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
}
|
||||
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const e = elements[i];
|
||||
if (e.kind !== SyntaxKind.OmittedExpression) {
|
||||
// Assignment for target = value.propName should highligh whole property, hence use e as source map node
|
||||
if (e.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
emitDestructuringAssignment(e, createElementAccess(value, createLiteral(i)), e);
|
||||
}
|
||||
else if (i === numElements - 1) {
|
||||
emitDestructuringAssignment((<SpreadElementExpression>e).expression, createArraySlice(value, i), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// Combine value and initializer
|
||||
value = value ? createDefaultValueCheck(value, initializer, target) : initializer;
|
||||
}
|
||||
else if (!value) {
|
||||
// Use 'void 0' in absence of value and initializer
|
||||
value = createVoidZero();
|
||||
}
|
||||
|
||||
const name = target.name;
|
||||
if (isBindingPattern(name)) {
|
||||
const elements = name.elements;
|
||||
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.
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitAssignment(name, value, target, target);
|
||||
}
|
||||
}
|
||||
|
||||
function createDefaultValueCheck(value: Expression, defaultValue: Expression, location: TextRange): Expression {
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
|
||||
return createConditional(
|
||||
createStrictEquality(value, createVoidZero()),
|
||||
createToken(SyntaxKind.QuestionToken),
|
||||
defaultValue,
|
||||
createToken(SyntaxKind.ColonToken),
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates either a PropertyAccessExpression or an ElementAccessExpression for the
|
||||
* right-hand side of a transformed destructuring assignment.
|
||||
*
|
||||
* @param expression The right-hand expression that is the source of the property.
|
||||
* @param propertyName The destructuring property name.
|
||||
*/
|
||||
function createDestructuringPropertyAccess(expression: Expression, propertyName: PropertyName): LeftHandSideExpression {
|
||||
if (isComputedPropertyName(propertyName)) {
|
||||
return createElementAccess(
|
||||
expression,
|
||||
ensureIdentifier(propertyName.expression, /*reuseIdentifierExpressions*/ false, /*location*/ propertyName, emitTempVariableAssignment)
|
||||
);
|
||||
}
|
||||
else if (isLiteralExpression(propertyName)) {
|
||||
const clone = getSynthesizedClone(propertyName);
|
||||
clone.text = unescapeIdentifier(clone.text);
|
||||
return createElementAccess(expression, clone);
|
||||
}
|
||||
else {
|
||||
if (isGeneratedIdentifier(propertyName)) {
|
||||
const clone = getSynthesizedClone(propertyName);
|
||||
clone.text = unescapeIdentifier(clone.text);
|
||||
return createPropertyAccess(expression, clone);
|
||||
}
|
||||
else {
|
||||
return createPropertyAccess(expression, createIdentifier(unescapeIdentifier(propertyName.text)));
|
||||
}
|
||||
}
|
||||
const name = createIdentifier(unescapeIdentifier(propertyName.text));
|
||||
return createPropertyAccess(expression, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,26 +538,20 @@ namespace ts {
|
||||
*
|
||||
* @param value the expression whose value needs to be bound.
|
||||
* @param reuseIdentifierExpressions true if identifier expressions can simply be returned;
|
||||
* false if it is necessary to always emit an identifier.
|
||||
* @param location The location to use for source maps and comments.
|
||||
* false if it is necessary to always emit an identifier.
|
||||
* @param emitTempVariableAssignment A callback used to emit a temporary variable.
|
||||
* @param visitor An optional callback used to visit the value.
|
||||
* @param location The location to use for source maps and comments.
|
||||
*/
|
||||
function ensureIdentifier(
|
||||
value: Expression,
|
||||
reuseIdentifierExpressions: boolean,
|
||||
location: TextRange,
|
||||
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
location: TextRange) {
|
||||
|
||||
if (isIdentifier(value) && reuseIdentifierExpressions) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
if (visitor) {
|
||||
value = visitNode(value, visitor, isExpression);
|
||||
}
|
||||
|
||||
return emitTempVariableAssignment(value, location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
/// <reference path="./destructuring.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
@ -404,6 +405,9 @@ namespace ts {
|
||||
case SyntaxKind.YieldExpression:
|
||||
return visitYieldExpression(<YieldExpression>node);
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
return visitSpreadElementExpression(<SpreadElementExpression>node);
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
return visitSuperKeyword();
|
||||
|
||||
@ -1129,7 +1133,7 @@ namespace ts {
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
flattenParameterDestructuring(parameter, temp, visitor)
|
||||
flattenDestructuring(parameter, temp, /*recordTempVariable*/ undefined, visitor)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
@ -1660,18 +1664,21 @@ namespace ts {
|
||||
*/
|
||||
function visitParenthesizedExpression(node: ParenthesizedExpression, needsDestructuringValue: boolean): ParenthesizedExpression {
|
||||
// If we are here it is most likely because our expression is a destructuring assignment.
|
||||
if (needsDestructuringValue) {
|
||||
if (!needsDestructuringValue) {
|
||||
// By default we always emit the RHS at the end of a flattened destructuring
|
||||
// expression. If we are in a state where we do not need the destructuring value,
|
||||
// we pass that information along to the children that care about it.
|
||||
switch (node.expression.kind) {
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return createParen(
|
||||
visitParenthesizedExpression(<ParenthesizedExpression>node.expression, /*needsDestructuringValue*/ true),
|
||||
/*location*/ node
|
||||
return updateParen(
|
||||
node,
|
||||
visitParenthesizedExpression(<ParenthesizedExpression>node.expression, /*needsDestructuringValue*/ false)
|
||||
);
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return createParen(
|
||||
visitBinaryExpression(<BinaryExpression>node.expression, /*needsDestructuringValue*/ true),
|
||||
/*location*/ node
|
||||
return updateParen(
|
||||
node,
|
||||
visitBinaryExpression(<BinaryExpression>node.expression, /*needsDestructuringValue*/ false)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1689,7 +1696,13 @@ 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 flattenDestructuringAssignment(context, node, needsDestructuringValue, hoistVariableDeclaration, visitor);
|
||||
return flattenDestructuringToExpression(
|
||||
<DestructuringAssignment>node,
|
||||
needsDestructuringValue,
|
||||
createAssignment,
|
||||
hoistVariableDeclaration,
|
||||
visitor
|
||||
);
|
||||
}
|
||||
|
||||
function visitVariableStatement(node: VariableStatement): Statement {
|
||||
@ -1701,15 +1714,17 @@ namespace ts {
|
||||
if (decl.initializer) {
|
||||
let assignment: Expression;
|
||||
if (isBindingPattern(decl.name)) {
|
||||
assignment = flattenVariableDestructuringToExpression(decl, hoistVariableDeclaration, /*createAssignmentCallback*/ undefined, visitor);
|
||||
assignment = flattenDestructuringToExpression(decl, /*needsValue*/ false, createAssignment, hoistVariableDeclaration, visitor);
|
||||
}
|
||||
else {
|
||||
assignment = createBinary(<Identifier>decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
|
||||
}
|
||||
(assignments || (assignments = [])).push(assignment);
|
||||
|
||||
assignments = append(assignments, assignment);
|
||||
}
|
||||
}
|
||||
if (assignments) {
|
||||
// TODO(rbuckton): use inlineExpressions.
|
||||
return createStatement(reduceLeft(assignments, (acc, v) => createBinary(v, SyntaxKind.CommaToken, acc)), node);
|
||||
}
|
||||
else {
|
||||
@ -1854,8 +1869,11 @@ namespace ts {
|
||||
if (isBindingPattern(node.name)) {
|
||||
const recordTempVariablesInLine = !enclosingVariableStatement
|
||||
|| !hasModifier(enclosingVariableStatement, ModifierFlags.Export);
|
||||
return flattenVariableDestructuring(node, /*value*/ undefined, visitor,
|
||||
recordTempVariablesInLine ? undefined : hoistVariableDeclaration);
|
||||
return flattenDestructuring(
|
||||
node,
|
||||
/*value*/ undefined,
|
||||
recordTempVariablesInLine ? undefined : hoistVariableDeclaration,
|
||||
visitor);
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
@ -1956,9 +1974,10 @@ namespace ts {
|
||||
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(
|
||||
const declarations = flattenDestructuring(
|
||||
firstOriginalDeclaration,
|
||||
createElementAccess(rhsReference, counter),
|
||||
/*recordTempVariable*/ undefined,
|
||||
visitor
|
||||
);
|
||||
|
||||
@ -2007,10 +2026,10 @@ namespace ts {
|
||||
// This is a destructuring pattern, so we flatten the destructuring instead.
|
||||
statements.push(
|
||||
createStatement(
|
||||
flattenDestructuringAssignment(
|
||||
context,
|
||||
flattenDestructuringToExpression(
|
||||
assignment,
|
||||
/*needsValue*/ false,
|
||||
createAssignment,
|
||||
hoistVariableDeclaration,
|
||||
visitor
|
||||
)
|
||||
@ -2840,7 +2859,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitSpanOfSpreadElements(chunk: Expression[]): VisitResult<Expression> {
|
||||
return map(chunk, visitExpressionOfSpreadElement);
|
||||
return map(chunk, visitSpreadElementExpression);
|
||||
}
|
||||
|
||||
function visitSpanOfNonSpreadElements(chunk: Expression[], multiLine: boolean, hasTrailingComma: boolean): VisitResult<Expression> {
|
||||
@ -2856,7 +2875,7 @@ namespace ts {
|
||||
*
|
||||
* @param node A SpreadElementExpression node.
|
||||
*/
|
||||
function visitExpressionOfSpreadElement(node: SpreadElementExpression) {
|
||||
function visitSpreadElementExpression(node: SpreadElementExpression) {
|
||||
return visitNode(node.expression, visitor, isExpression);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
@ -45,6 +46,7 @@ namespace ts {
|
||||
let currentSourceFile: SourceFile; // The current file.
|
||||
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
|
||||
let noSubstitution: Map<boolean>; // Set of nodes for which substitution rules should be ignored.
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
@ -62,6 +64,7 @@ namespace ts {
|
||||
|
||||
currentSourceFile = node;
|
||||
currentModuleInfo = moduleInfoMap[getOriginalNodeId(node)] = collectExternalModuleInfo(node, resolver);
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
// Perform the transformation.
|
||||
const transformModule = transformModuleDelegates[moduleKind] || transformModuleDelegates[ModuleKind.None];
|
||||
@ -69,6 +72,7 @@ namespace ts {
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentModuleInfo = undefined;
|
||||
helperState = undefined;
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
|
||||
@ -759,10 +763,12 @@ namespace ts {
|
||||
*/
|
||||
function transformInitializedVariable(node: VariableDeclaration): Expression {
|
||||
if (isBindingPattern(node.name)) {
|
||||
return flattenVariableDestructuringToExpression(
|
||||
return flattenDestructuringToExpression(
|
||||
node,
|
||||
/*needsValue*/ false,
|
||||
createExportExpression,
|
||||
hoistVariableDeclaration,
|
||||
createExportExpression
|
||||
/*visitor*/ undefined
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
@ -40,6 +41,7 @@ namespace ts {
|
||||
let hoistedStatements: Statement[];
|
||||
let enclosingBlockScopedContainer: Node;
|
||||
let noSubstitution: Map<boolean>; // Set of nodes for which substitution rules should be ignored.
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
@ -58,6 +60,7 @@ namespace ts {
|
||||
const id = getOriginalNodeId(node);
|
||||
currentSourceFile = node;
|
||||
enclosingBlockScopedContainer = node;
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
// System modules have the following shape:
|
||||
//
|
||||
@ -131,6 +134,7 @@ namespace ts {
|
||||
contextObject = undefined;
|
||||
hoistedStatements = undefined;
|
||||
enclosingBlockScopedContainer = undefined;
|
||||
helperState = undefined;
|
||||
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
@ -818,7 +822,7 @@ namespace ts {
|
||||
function transformInitializedVariable(node: VariableDeclaration, isExportedDeclaration: boolean): Expression {
|
||||
const createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment;
|
||||
return isBindingPattern(node.name)
|
||||
? flattenVariableDestructuringToExpression(node, hoistVariableDeclaration, createAssignment, destructuringVisitor)
|
||||
? flattenDestructuringToExpression(node, /*needsValue*/ false, createAssignment, hoistVariableDeclaration, destructuringVisitor)
|
||||
: createAssignment(node.name, visitNode(node.initializer, destructuringVisitor, isExpression));
|
||||
}
|
||||
|
||||
@ -1469,9 +1473,8 @@ namespace ts {
|
||||
*/
|
||||
function visitDestructuringAssignment(node: DestructuringAssignment): VisitResult<Expression> {
|
||||
if (hasExportedReferenceInDestructuringTarget(node.left)) {
|
||||
return flattenDestructuringAssignment(context, node, /*needsValue*/ true, hoistVariableDeclaration, destructuringVisitor);
|
||||
return flattenDestructuringToExpression(node, /*needsValue*/ true, createAssignment, hoistVariableDeclaration, destructuringVisitor);
|
||||
}
|
||||
|
||||
return visitEachChild(node, destructuringVisitor, context);
|
||||
}
|
||||
|
||||
@ -1481,7 +1484,7 @@ namespace ts {
|
||||
* @param node The destructuring target.
|
||||
*/
|
||||
function hasExportedReferenceInDestructuringTarget(node: Expression | ObjectLiteralElementLike): boolean {
|
||||
if (isAssignmentExpression(node)) {
|
||||
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
|
||||
return hasExportedReferenceInDestructuringTarget(node.left);
|
||||
}
|
||||
else if (isSpreadElementExpression(node)) {
|
||||
|
||||
@ -2312,12 +2312,7 @@ namespace ts {
|
||||
function transformInitializedVariable(node: VariableDeclaration): Expression {
|
||||
const name = node.name;
|
||||
if (isBindingPattern(name)) {
|
||||
return flattenVariableDestructuringToExpression(
|
||||
node,
|
||||
hoistVariableDeclaration,
|
||||
createNamespaceExportExpression,
|
||||
visitor
|
||||
);
|
||||
return flattenDestructuringToExpression(node, /*needsValue*/ false, createNamespaceExportExpression, hoistVariableDeclaration, visitor);
|
||||
}
|
||||
else {
|
||||
return createAssignment(
|
||||
|
||||
@ -635,9 +635,9 @@ namespace ts {
|
||||
|
||||
export interface ParameterDeclaration extends Declaration {
|
||||
kind: SyntaxKind.Parameter;
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
|
||||
name: BindingName; // Declared parameter name
|
||||
questionToken?: QuestionToken; // Present on optional parameter
|
||||
questionToken?: QuestionToken; // Present on optional parameter
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
@ -645,7 +645,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 binding element
|
||||
name: BindingName; // Declared binding element name
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
@ -671,7 +671,12 @@ namespace ts {
|
||||
name?: PropertyName;
|
||||
}
|
||||
|
||||
export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | MethodDeclaration | AccessorDeclaration;
|
||||
export type ObjectLiteralElementLike
|
||||
= PropertyAssignment
|
||||
| ShorthandPropertyAssignment
|
||||
| MethodDeclaration
|
||||
| AccessorDeclaration
|
||||
;
|
||||
|
||||
export interface PropertyAssignment extends ObjectLiteralElement {
|
||||
kind: SyntaxKind.PropertyAssignment;
|
||||
@ -712,6 +717,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface BindingPattern extends Node {
|
||||
kind: SyntaxKind.ObjectBindingPattern | SyntaxKind.ArrayBindingPattern;
|
||||
elements: NodeArray<BindingElement | ArrayBindingElement>;
|
||||
}
|
||||
|
||||
@ -1157,16 +1163,16 @@ namespace ts {
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export interface AssignmentExpression extends BinaryExpression {
|
||||
export interface AssignmentExpression<TKind extends AssignmentOperator> extends BinaryExpression {
|
||||
left: LeftHandSideExpression;
|
||||
operatorToken: Token<SyntaxKind.EqualsToken>;
|
||||
operatorToken: Token<TKind>;
|
||||
}
|
||||
|
||||
export interface ObjectDestructuringAssignment extends AssignmentExpression {
|
||||
export interface ObjectDestructuringAssignment extends AssignmentExpression<SyntaxKind.EqualsToken> {
|
||||
left: ObjectLiteralExpression;
|
||||
}
|
||||
|
||||
export interface ArrayDestructuringAssignment extends AssignmentExpression {
|
||||
export interface ArrayDestructuringAssignment extends AssignmentExpression<SyntaxKind.EqualsToken> {
|
||||
left: ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
|
||||
@ -3084,19 +3084,21 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isAssignmentExpression(node: Node): node is AssignmentExpression {
|
||||
export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression<SyntaxKind.EqualsToken>;
|
||||
export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: false): node is AssignmentExpression<AssignmentOperator>;
|
||||
export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: boolean): node is AssignmentExpression<AssignmentOperator> {
|
||||
return isBinaryExpression(node)
|
||||
&& isAssignmentOperator(node.operatorToken.kind)
|
||||
&& (excludeCompoundAssignment
|
||||
? node.operatorToken.kind === SyntaxKind.EqualsToken
|
||||
: isAssignmentOperator(node.operatorToken.kind))
|
||||
&& isLeftHandSideExpression(node.left);
|
||||
}
|
||||
|
||||
export function isDestructuringAssignment(node: Node): node is DestructuringAssignment {
|
||||
if (isBinaryExpression(node)) {
|
||||
if (node.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const kind = node.left.kind;
|
||||
return kind === SyntaxKind.ObjectLiteralExpression
|
||||
|| kind === SyntaxKind.ArrayLiteralExpression;
|
||||
}
|
||||
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
|
||||
const kind = node.left.kind;
|
||||
return kind === SyntaxKind.ObjectLiteralExpression
|
||||
|| kind === SyntaxKind.ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@ -549,11 +549,11 @@ namespace ts {
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T;
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray<Node>) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T;
|
||||
export function visitNode(node: Node, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: Node[]) => Node, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): Node {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
if (node === undefined || visitor === undefined) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const visited = visitor(node);
|
||||
const visited = visitor(aggregateTransformFlags(node));
|
||||
if (visited === node) {
|
||||
return node;
|
||||
}
|
||||
@ -621,7 +621,7 @@ namespace ts {
|
||||
// Visit each original node.
|
||||
for (let i = 0; i < count; i++) {
|
||||
const node = nodes[i + start];
|
||||
const visited = node !== undefined ? visitor(node) : undefined;
|
||||
const visited = node !== undefined ? visitor(aggregateTransformFlags(node)) : undefined;
|
||||
if (updated !== undefined || visited === undefined || visited !== node) {
|
||||
if (updated === undefined) {
|
||||
// Ensure we have a copy of `nodes`, up to the current index.
|
||||
|
||||
@ -37,17 +37,17 @@ x = [true][0];
|
||||
x; // boolean
|
||||
_a = [1][0], x = _a === void 0 ? "" : _a;
|
||||
x; // string | number
|
||||
(_b = { x: true }, x = _b.x, _b);
|
||||
(x = { x: true }.x);
|
||||
x; // boolean
|
||||
(_c = { y: 1 }, x = _c.y, _c);
|
||||
(x = { y: 1 }.y);
|
||||
x; // number
|
||||
(_d = { x: true }, _e = _d.x, x = _e === void 0 ? "" : _e, _d);
|
||||
(_b = { x: true }.x, x = _b === void 0 ? "" : _b);
|
||||
x; // string | boolean
|
||||
(_f = { y: 1 }, _g = _f.y, x = _g === void 0 ? /a/ : _g, _f);
|
||||
(_c = { y: 1 }.y, x = _c === void 0 ? /a/ : _c);
|
||||
x; // number | RegExp
|
||||
var a;
|
||||
for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
|
||||
x = a_1[_i];
|
||||
x; // string
|
||||
}
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
var _a, _b, _c;
|
||||
|
||||
@ -81,8 +81,8 @@ var B = (function (_super) {
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
B.prototype.advanced = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var f, a, b, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
var f, a, b;
|
||||
return __generator(this, function (_a) {
|
||||
f = function () { };
|
||||
// call with property access
|
||||
_super.prototype.x.call(this);
|
||||
@ -95,9 +95,9 @@ var B = (function (_super) {
|
||||
// element access (assign)
|
||||
_super.prototype["x"] = f;
|
||||
// destructuring assign with property access
|
||||
(_a = { f: f }, super.x = _a.f, _a);
|
||||
(super.x = { f: f }.f);
|
||||
// destructuring assign with element access
|
||||
(_b = { f: f }, super["x"] = _b.f, _b);
|
||||
(super["x"] = { f: f }.f);
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
|
||||
@ -65,11 +65,11 @@ function f5(_a) {
|
||||
var _f = foo(), bar6 = [{ bar: "bar" }][0][_f];
|
||||
var _g = foo.toExponential(), bar7 = [{ bar: "bar" }][0][_g];
|
||||
// destructuring assignment
|
||||
(_h = { bar: "bar" }, _j = foo, bar = _h[_j], _h);
|
||||
(_k = { bar: "bar" }, _l = "bar", bar2 = _k[_l], _k);
|
||||
(_m = { bar: "bar" }, _o = foo2(), bar3 = _m[_o], _m);
|
||||
_p = foo, bar4 = [{ bar: "bar" }][0][_p];
|
||||
_q = foo2(), bar5 = [{ bar: "bar" }][0][_q];
|
||||
_r = foo(), bar4 = [{ bar: "bar" }][0][_r];
|
||||
_s = (1 + {}), bar4 = [{ bar: "bar" }][0][_s];
|
||||
var _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
||||
(_h = foo, bar = { bar: "bar" }[_h]);
|
||||
(_j = "bar", bar2 = { bar: "bar" }[_j]);
|
||||
(_k = foo2(), bar3 = { bar: "bar" }[_k]);
|
||||
_l = foo, bar4 = [{ bar: "bar" }][0][_l];
|
||||
_m = foo2(), bar5 = [{ bar: "bar" }][0][_m];
|
||||
_o = foo(), bar4 = [{ bar: "bar" }][0][_o];
|
||||
_p = (1 + {}), bar4 = [{ bar: "bar" }][0][_p];
|
||||
var _h, _j, _k, _l, _m, _o, _p;
|
||||
|
||||
@ -300,8 +300,8 @@ function f18() {
|
||||
var a;
|
||||
var b;
|
||||
var aa;
|
||||
(_a = { a: a, b: b }, a = _a.a, b = _a.b, _a);
|
||||
(_b = { b: b, a: a }, a = _b.a, b = _b.b, _b);
|
||||
(_a = { a: a, b: b }, a = _a.a, b = _a.b);
|
||||
(_b = { b: b, a: a }, a = _b.a, b = _b.b);
|
||||
_c = [a, b], aa[0] = _c[0], b = _c[1];
|
||||
_d = [b, a], a = _d[0], b = _d[1]; // Error
|
||||
_e = [2, "def"], _f = _e[0], a = _f === void 0 ? 1 : _f, _g = _e[1], b = _g === void 0 ? "abc" : _g;
|
||||
@ -311,7 +311,7 @@ function f19() {
|
||||
var a, b;
|
||||
_a = [1, 2], a = _a[0], b = _a[1];
|
||||
_b = [b, a], a = _b[0], b = _b[1];
|
||||
(_c = { b: b, a: a }, a = _c.a, b = _c.b, _c);
|
||||
(_c = { b: b, a: a }, a = _c.a, b = _c.b);
|
||||
_d = [[2, 3]][0], _e = _d === void 0 ? [1, 2] : _d, a = _e[0], b = _e[1];
|
||||
var x = (_f = [1, 2], a = _f[0], b = _f[1], _f);
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
|
||||
@ -7,5 +7,5 @@ let x = 0;
|
||||
//// [destructuringAssignmentWithDefault.js]
|
||||
var a = {};
|
||||
var x = 0;
|
||||
(_a = a.x, x = _a === void 0 ? 1 : _a, a);
|
||||
(_a = a.x, x = _a === void 0 ? 1 : _a);
|
||||
var _a;
|
||||
|
||||
@ -9,8 +9,8 @@ let x, y, z, a1, a2, a3;
|
||||
//// [emptyAssignmentPatterns02_ES5.js]
|
||||
var a;
|
||||
var x, y, z, a1, a2, a3;
|
||||
(x = a.x, y = a.y, z = a.z, a);
|
||||
(a1 = a[0], a2 = a[1], a3 = a[2], a);
|
||||
(x = a.x, y = a.y, z = a.z);
|
||||
(a1 = a[0], a2 = a[1], a3 = a[2]);
|
||||
|
||||
|
||||
//// [emptyAssignmentPatterns02_ES5.d.ts]
|
||||
|
||||
@ -9,9 +9,8 @@ let x, y, z, a1, a2, a3;
|
||||
//// [emptyAssignmentPatterns04_ES5.js]
|
||||
var a;
|
||||
var x, y, z, a1, a2, a3;
|
||||
(_a = a, x = _a.x, y = _a.y, z = _a.z, _a);
|
||||
(_b = a, a1 = _b[0], a2 = _b[1], a3 = _b[2], _b);
|
||||
var _a, _b;
|
||||
(x = a.x, y = a.y, z = a.z);
|
||||
(a1 = a[0], a2 = a[1], a3 = a[2]);
|
||||
|
||||
|
||||
//// [emptyAssignmentPatterns04_ES5.d.ts]
|
||||
|
||||
@ -28,7 +28,6 @@ if (true) {
|
||||
var x_1 = { x: 0 }.x;
|
||||
var y_1 = { y: 0 }.y;
|
||||
var z_1;
|
||||
(_a = { z: 0 }, z_1 = _a.z, _a);
|
||||
(_b = { z: 0 }, z_1 = _b.z, _b);
|
||||
(z_1 = { z: 0 }.z);
|
||||
(z_1 = { z: 0 }.z);
|
||||
}
|
||||
var _a, _b;
|
||||
|
||||
@ -45,10 +45,10 @@ function f1() {
|
||||
// Missing properties
|
||||
function f2() {
|
||||
var x, y;
|
||||
(_a = {}, x = _a.x, y = _a.y, _a);
|
||||
(_b = {}, _c = _b.x, x = _c === void 0 ? 1 : _c, y = _b.y, _b);
|
||||
(_d = {}, x = _d.x, _e = _d.y, y = _e === void 0 ? 1 : _e, _d);
|
||||
(_f = {}, _g = _f.x, x = _g === void 0 ? 1 : _g, _h = _f.y, y = _h === void 0 ? 1 : _h, _f);
|
||||
(_a = {}, x = _a.x, y = _a.y);
|
||||
(_b = {}, _c = _b.x, x = _c === void 0 ? 1 : _c, y = _b.y);
|
||||
(_d = {}, x = _d.x, _e = _d.y, y = _e === void 0 ? 1 : _e);
|
||||
(_f = {}, _g = _f.x, x = _g === void 0 ? 1 : _g, _h = _f.y, y = _h === void 0 ? 1 : _h);
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||||
}
|
||||
// Excess properties
|
||||
@ -62,8 +62,8 @@ function f3() {
|
||||
function f4() {
|
||||
var x, y;
|
||||
({ x: 0, y: 0 });
|
||||
(_a = { x: 0, y: 0 }, x = _a.x, _a);
|
||||
(_b = { x: 0, y: 0 }, y = _b.y, _b);
|
||||
(_c = { x: 0, y: 0 }, x = _c.x, y = _c.y, _c);
|
||||
var _a, _b, _c;
|
||||
(x = { x: 0, y: 0 }.x);
|
||||
(y = { x: 0, y: 0 }.y);
|
||||
(_a = { x: 0, y: 0 }, x = _a.x, y = _a.y);
|
||||
var _a;
|
||||
}
|
||||
|
||||
@ -176,63 +176,63 @@ function foo({a = 4, b = { x: 5 }}) {
|
||||
});
|
||||
(function () {
|
||||
var y;
|
||||
(_a = { y: 1 }, _b = _a.y, y = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { y: 1 }.y, y = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y;
|
||||
(_a = { y: 1 }, _b = _a.y, y = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { y: 1 }.y, y = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y0;
|
||||
(_a = { y0: 1 }, _b = _a.y0, y0 = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { y0: 1 }.y0, y0 = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y0;
|
||||
(_a = { y0: 1 }, _b = _a.y0, y0 = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { y0: 1 }.y0, y0 = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y1;
|
||||
(_a = {}, _b = _a.y1, y1 = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = {}.y1, y1 = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y1;
|
||||
(_a = {}, _b = _a.y1, y1 = _b === void 0 ? 5 : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = {}.y1, y1 = _a === void 0 ? 5 : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var y2, y3;
|
||||
(_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c, _a);
|
||||
(_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c);
|
||||
var _a, _b, _c;
|
||||
});
|
||||
(function () {
|
||||
var y2, y3;
|
||||
(_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c, _a);
|
||||
(_a = {}, _b = _a.y2, y2 = _b === void 0 ? 5 : _b, _c = _a.y3, y3 = _c === void 0 ? { x: 1 } : _c);
|
||||
var _a, _b, _c;
|
||||
});
|
||||
(function () {
|
||||
var y4, y5;
|
||||
(_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c, _a);
|
||||
(_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c);
|
||||
var _a, _b, _c;
|
||||
});
|
||||
(function () {
|
||||
var y4, y5;
|
||||
(_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c, _a);
|
||||
(_a = {}, _b = _a.y4, y4 = _b === void 0 ? 5 : _b, _c = _a.y5, y5 = _c === void 0 ? { x: 1 } : _c);
|
||||
var _a, _b, _c;
|
||||
});
|
||||
(function () {
|
||||
var z;
|
||||
(_a = { z: { x: 1 } }, _b = _a.z, z = _b === void 0 ? { x: 5 } : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { z: { x: 1 } }.z, z = _a === void 0 ? { x: 5 } : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var z;
|
||||
(_a = { z: { x: 1 } }, _b = _a.z, z = _b === void 0 ? { x: 5 } : _b, _a);
|
||||
var _a, _b;
|
||||
(_a = { z: { x: 1 } }.z, z = _a === void 0 ? { x: 5 } : _a);
|
||||
var _a;
|
||||
});
|
||||
(function () {
|
||||
var a = { s: s };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user