Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 38 additions & 23 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3210,22 +3210,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}

function ensureIdentifier(expr: Expression): Expression {
if (expr.kind !== SyntaxKind.Identifier) {
let identifier = createTempVariable(TempFlags.Auto);
if (!canDefineTempVariablesInPlace) {
recordTempDeclaration(identifier);
}
emitAssignment(identifier, expr);
expr = identifier;
/**
* Ensures that there exists a declared identifier whose value holds the given expression.
* This function is useful to ensure that the expression's value can be read from in subsequent expressions.
* Unless 'reuseIdentifierExpressions' is false, 'expr' will be returned if it is just an identifier.
*
* @param expr 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.
*/
function ensureIdentifier(expr: Expression, reuseIdentifierExpressions: boolean): Expression {
if (expr.kind === SyntaxKind.Identifier && reuseIdentifierExpressions) {
return expr;
}

let identifier = createTempVariable(TempFlags.Auto);
if (!canDefineTempVariablesInPlace) {
recordTempDeclaration(identifier);
}
return expr;
emitAssignment(identifier, expr);
return identifier;
}

function createDefaultValueCheck(value: Expression, defaultValue: Expression): Expression {
// The value expression will be evaluated twice, so for anything but a simple identifier
// we need to generate a temporary variable
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
// Return the expression 'value === void 0 ? defaultValue : value'
let equals = <BinaryExpression>createSynthesizedNode(SyntaxKind.BinaryExpression);
equals.left = value;
Expand Down Expand Up @@ -3276,7 +3286,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (properties.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
}
for (let p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
Expand All @@ -3291,7 +3301,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (elements.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
}
for (let i = 0; i < elements.length; i++) {
let e = elements[i];
Expand Down Expand Up @@ -3336,7 +3346,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (root.parent.kind !== SyntaxKind.ParenthesizedExpression) {
write("(");
}
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
emitDestructuringAssignment(target, value);
write(", ");
emit(value);
Expand All @@ -3346,7 +3356,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}

function emitBindingElement(target: BindingElement, value: Expression) {
function emitBindingElement(target: BindingElement | VariableDeclaration, value: Expression) {
if (target.initializer) {
// Combine value and initializer
value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
Expand All @@ -3356,14 +3366,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
value = createVoidZero();
}
if (isBindingPattern(target.name)) {
let pattern = <BindingPattern>target.name;
let elements = pattern.elements;
if (elements.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
}
for (let i = 0; i < elements.length; i++) {
const pattern = <BindingPattern>target.name;
const elements = pattern.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);
}

for (let i = 0; i < numElements; i++) {
let element = elements[i];
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
// Rewrite element to a declaration with an initializer that fetches property
Expand All @@ -3375,7 +3390,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Rewrite element to a declaration that accesses array element at index i
emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
}
else if (i === elements.length - 1) {
else if (i === numElements - 1) {
emitBindingElement(element, createSliceCall(value, i));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyArrayBindingPatternParameter01.ts]


function f([]) {
var x, y, z;
}
Expand All @@ -9,3 +8,7 @@ function f([]) {
function f(_a) {
var x, y, z;
}


//// [emptyArrayBindingPatternParameter01.d.ts]
declare function f([]: any[]): void;
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter01.ts ===


function f([]) {
>f : Symbol(f, Decl(emptyArrayBindingPatternParameter01.ts, 0, 0))

var x, y, z;
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter01.ts, 3, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter01.ts, 3, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter01.ts, 3, 13))
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter01.ts, 2, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter01.ts, 2, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter01.ts, 2, 13))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter01.ts ===


function f([]) {
>f : ([]: any[]) => void

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyArrayBindingPatternParameter02.ts]


function f(a, []) {
var x, y, z;
}
Expand All @@ -9,3 +8,7 @@ function f(a, []) {
function f(a, _a) {
var x, y, z;
}


//// [emptyArrayBindingPatternParameter02.d.ts]
declare function f(a: any, []: any[]): void;
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter02.ts ===


function f(a, []) {
>f : Symbol(f, Decl(emptyArrayBindingPatternParameter02.ts, 0, 0))
>a : Symbol(a, Decl(emptyArrayBindingPatternParameter02.ts, 2, 11))
>a : Symbol(a, Decl(emptyArrayBindingPatternParameter02.ts, 1, 11))

var x, y, z;
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter02.ts, 3, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter02.ts, 3, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter02.ts, 3, 13))
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter02.ts, 2, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter02.ts, 2, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter02.ts, 2, 13))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter02.ts ===


function f(a, []) {
>f : (a: any, []: any[]) => void
>a : any
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyArrayBindingPatternParameter03.ts]


function f(a, []) {
var x, y, z;
}
Expand All @@ -9,3 +8,7 @@ function f(a, []) {
function f(a, _a) {
var x, y, z;
}


//// [emptyArrayBindingPatternParameter03.d.ts]
declare function f(a: any, []: any[]): void;
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter03.ts ===


function f(a, []) {
>f : Symbol(f, Decl(emptyArrayBindingPatternParameter03.ts, 0, 0))
>a : Symbol(a, Decl(emptyArrayBindingPatternParameter03.ts, 2, 11))
>a : Symbol(a, Decl(emptyArrayBindingPatternParameter03.ts, 1, 11))

var x, y, z;
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter03.ts, 3, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter03.ts, 3, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter03.ts, 3, 13))
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter03.ts, 2, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter03.ts, 2, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter03.ts, 2, 13))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter03.ts ===


function f(a, []) {
>f : (a: any, []: any[]) => void
>a : any
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyArrayBindingPatternParameter04.ts]


function f([] = [1,2,3,4]) {
var x, y, z;
}
Expand All @@ -10,3 +9,7 @@ function f(_a) {
var _a = [1, 2, 3, 4];
var x, y, z;
}


//// [emptyArrayBindingPatternParameter04.d.ts]
declare function f([]?: number[]): void;
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter04.ts ===


function f([] = [1,2,3,4]) {
>f : Symbol(f, Decl(emptyArrayBindingPatternParameter04.ts, 0, 0))

var x, y, z;
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter04.ts, 3, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter04.ts, 3, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter04.ts, 3, 13))
>x : Symbol(x, Decl(emptyArrayBindingPatternParameter04.ts, 2, 7))
>y : Symbol(y, Decl(emptyArrayBindingPatternParameter04.ts, 2, 10))
>z : Symbol(z, Decl(emptyArrayBindingPatternParameter04.ts, 2, 13))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
=== tests/cases/conformance/es6/destructuring/emptyArrayBindingPatternParameter04.ts ===


function f([] = [1,2,3,4]) {
>f : ([]?: number[]) => void
>[1,2,3,4] : number[]
Expand Down
4 changes: 4 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns01_ES5.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ var a: any;
var a;
(a);
(a);


//// [emptyAssignmentPatterns01_ES5.d.ts]
declare var a: any;
4 changes: 4 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns01_ES6.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ var a: any;
var a;
({} = a);
([] = a);


//// [emptyAssignmentPatterns01_ES6.d.ts]
declare var a: any;
5 changes: 5 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns02_ES5.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ 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));


//// [emptyAssignmentPatterns02_ES5.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;
5 changes: 5 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns02_ES6.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ var a;
let x, y, z, a1, a2, a3;
({} = { x, y, z } = a);
([] = [a1, a2, a3] = a);


//// [emptyAssignmentPatterns02_ES6.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;
4 changes: 4 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns03_ES5.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ var a: any;
var a;
(a);
(a);


//// [emptyAssignmentPatterns03_ES5.d.ts]
declare var a: any;
4 changes: 4 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns03_ES6.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ var a: any;
var a;
({} = {} = a);
([] = [] = a);


//// [emptyAssignmentPatterns03_ES6.d.ts]
declare var a: any;
5 changes: 5 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns04_ES5.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ 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;


//// [emptyAssignmentPatterns04_ES5.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;
5 changes: 5 additions & 0 deletions tests/baselines/reference/emptyAssignmentPatterns04_ES6.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ var a;
let x, y, z, a1, a2, a3;
({ x, y, z } = {} = a);
([a1, a2, a3] = [] = a);


//// [emptyAssignmentPatterns04_ES6.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyObjectBindingPatternParameter01.ts]


function f({}) {
var x, y, z;
}
Expand All @@ -9,3 +8,7 @@ function f({}) {
function f(_a) {
var x, y, z;
}


//// [emptyObjectBindingPatternParameter01.d.ts]
declare function f({}: {}): void;
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
=== tests/cases/conformance/es6/destructuring/emptyObjectBindingPatternParameter01.ts ===


function f({}) {
>f : Symbol(f, Decl(emptyObjectBindingPatternParameter01.ts, 0, 0))

var x, y, z;
>x : Symbol(x, Decl(emptyObjectBindingPatternParameter01.ts, 3, 7))
>y : Symbol(y, Decl(emptyObjectBindingPatternParameter01.ts, 3, 10))
>z : Symbol(z, Decl(emptyObjectBindingPatternParameter01.ts, 3, 13))
>x : Symbol(x, Decl(emptyObjectBindingPatternParameter01.ts, 2, 7))
>y : Symbol(y, Decl(emptyObjectBindingPatternParameter01.ts, 2, 10))
>z : Symbol(z, Decl(emptyObjectBindingPatternParameter01.ts, 2, 13))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
=== tests/cases/conformance/es6/destructuring/emptyObjectBindingPatternParameter01.ts ===


function f({}) {
>f : ({}: {}) => void

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//// [emptyObjectBindingPatternParameter02.ts]


function f(a, {}) {
var x, y, z;
}
Expand All @@ -9,3 +8,7 @@ function f(a, {}) {
function f(a, _a) {
var x, y, z;
}


//// [emptyObjectBindingPatternParameter02.d.ts]
declare function f(a: any, {}: {}): void;
Loading