diff --git a/test/language/expressions/optional-chaining/iteration-statement-do.js b/test/language/expressions/optional-chaining/iteration-statement-do.js new file mode 100644 index 0000000000..5a82cc23cd --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-do.js @@ -0,0 +1,18 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain in test portion of do while statement +info: | + IterationStatement + do Statement while (OptionalExpression) +features: [optional-chaining] +---*/ +let count = 0; +const obj = {a: true}; +do { + count++; + break; +} while (obj?.a); +assert.sameValue(1, count); diff --git a/test/language/expressions/optional-chaining/iteration-statement-for-await-of.js b/test/language/expressions/optional-chaining/iteration-statement-for-await-of.js new file mode 100644 index 0000000000..6d414965ab --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-for-await-of.js @@ -0,0 +1,35 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain RHS of for await statement +info: | + IterationStatement + for await (LeftHandSideExpression of AssignmentExpression) Statement +features: [optional-chaining] +flags: [async] +---*/ +const obj = { + iterable: { + [Symbol.asyncIterator]() { + return { + i: 0, + next() { + if (this.i < 3) { + return Promise.resolve({ value: this.i++, done: false }); + } + return Promise.resolve({ done: true }); + } + }; + } + } +}; +async function checkAssertions() { + let count = 0; + for await (const num of obj?.iterable) { + count += num; + } + assert.sameValue(3, count); +} +checkAssertions().then($DONE, $DONE); diff --git a/test/language/expressions/optional-chaining/iteration-statement-for-in.js b/test/language/expressions/optional-chaining/iteration-statement-for-in.js new file mode 100644 index 0000000000..2823b8053b --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-for-in.js @@ -0,0 +1,22 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain in test portion of do while statement +info: | + IterationStatement + for (LeftHandSideExpression in Expression) Statement +features: [optional-chaining] +---*/ +const obj = { + inner: { + a: 1, + b: 2 + } +}; +let str = ''; +for (const key in obj?.inner) { + str += key; +} +assert.sameValue('ab', str); diff --git a/test/language/expressions/optional-chaining/iteration-statement-for-of-type-error.js b/test/language/expressions/optional-chaining/iteration-statement-for-of-type-error.js new file mode 100644 index 0000000000..3cd18cd48f --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-for-of-type-error.js @@ -0,0 +1,28 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain returning undefined in RHS of for of statement +info: | + IterationStatement + for (LeftHandSideExpression of Expression) Statement +features: [optional-chaining] +---*/ + +assert.throws(TypeError, function() { + for (const key of {}?.a) ; +}); + +assert.throws(TypeError, function() { + for (const key of {}?.a) {} +}); + +const obj = undefined; +assert.throws(TypeError, function() { + for (const key of obj?.a) {} +}); + +assert.throws(TypeError, function() { + for (const key of obj?.a); +}); diff --git a/test/language/expressions/optional-chaining/iteration-statement-for.js b/test/language/expressions/optional-chaining/iteration-statement-for.js new file mode 100644 index 0000000000..c6d78a3181 --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-for.js @@ -0,0 +1,43 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain in init/test/update of for statement +info: | + IterationStatement + for (Expression; Expression; Expression) Statement +features: [optional-chaining] +---*/ + +// OptionalExpression in test. +let count; +const obj = {a: true}; +for (count = 0; obj?.a; count++) { + if (count > 0) break; +} +assert.sameValue(count, 1); + +// OptionalExpression in init/test/update. +let count2 = 0; +const obj2 = undefined; + +for (obj?.a; obj2?.a; obj?.a) { count2++; } +assert.sameValue(count2, 0); + +for (obj?.a; undefined?.a; obj?.a) { count2++; } +assert.sameValue(count2, 0); + +// Short-circuiting +let touched = 0; +const obj3 = { + get a() { + count++; + return undefined; // explicit for clarity + } +}; +for (count = 0; true; obj3?.a?.[touched++]) { + if (count > 0) { break; } +} +assert.sameValue(count, 1); +assert.sameValue(touched, 0); diff --git a/test/language/expressions/optional-chaining/iteration-statement-while.js b/test/language/expressions/optional-chaining/iteration-statement-while.js new file mode 100644 index 0000000000..80fffa9296 --- /dev/null +++ b/test/language/expressions/optional-chaining/iteration-statement-while.js @@ -0,0 +1,18 @@ +// Copyright 2019 Google, LLC. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: prod-OptionalExpression +description: > + optional chain in test portion of while statement +info: | + IterationStatement + while (Expression) Statement +features: [optional-chaining] +---*/ +let count = 0; +const obj = {a: true}; +while (obj?.a) { + count++; + break; +} +assert.sameValue(1, count);