Skip to content
Open
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
7 changes: 6 additions & 1 deletion tsc/internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -5781,7 +5781,12 @@ func (p *Parser) parseArrayLiteralExpression() *ast.Expression {
openBracketPosition := p.scanner.TokenStart()
openBracketParsed := p.parseExpected(ast.KindOpenBracketToken)
multiLine := p.hasPrecedingLineBreak()
elements := p.parseDelimitedList(PCArrayLiteralMembers, (*Parser).parseArgumentOrArrayLiteralElement)
// The [~In] of a `for` statement head does not reach into array literals:
// ElementList elements are AssignmentExpression[+In]. Parse them with `in` allowed,
// as is already done for object literal property values and call arguments.
elements := p.doInContext(ast.NodeFlagsDisallowInContext, false, func(p *Parser) *ast.NodeList {
return p.parseDelimitedList(PCArrayLiteralMembers, (*Parser).parseArgumentOrArrayLiteralElement)
})
p.parseExpectedMatchingBrackets(ast.KindOpenBracketToken, ast.KindCloseBracketToken, openBracketParsed, openBracketPosition)
return p.finishNode(p.factory.NewArrayLiteralExpression(elements, multiLine), pos)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//// [tests/cases/compiler/arrayLiteralInOperatorInForInitializer.ts] ////

//// [arrayLiteralInOperatorInForInitializer.ts]
// The `in` operator is allowed in an array literal that appears in the head of
// a `for` statement: the for head's [~In] parameter does not reach into
// array literals (ElementList : AssignmentExpression[+In]).

const o = { a: 1 };
const k = "a";

for (let i = 0, has = [k in o]; i < 1; i++) {
console.log(has);
}

for (let i = 0, has = [k in o, "b" in o, !(k in o)]; i < 1; i++) {
console.log(has);
}

let x: any;
for ([x = "x" in {}] of [[]]) {
console.log(x);
}

// The initializer of a `for` statement still ends at `in`, so that `for-in`
// statements keep parsing as before.
for (const key in o) {
console.log(key);
}


//// [arrayLiteralInOperatorInForInitializer.js]
"use strict";
// The `in` operator is allowed in an array literal that appears in the head of
// a `for` statement: the for head's [~In] parameter does not reach into
// array literals (ElementList : AssignmentExpression[+In]).
const o = { a: 1 };
const k = "a";
for (let i = 0, has = [k in o]; i < 1; i++) {
console.log(has);
}
for (let i = 0, has = [k in o, "b" in o, !(k in o)]; i < 1; i++) {
console.log(has);
}
let x;
for ([x = "x" in {}] of [[]]) {
console.log(x);
}
// The initializer of a `for` statement still ends at `in`, so that `for-in`
// statements keep parsing as before.
for (const key in o) {
console.log(key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//// [tests/cases/compiler/arrayLiteralInOperatorInForInitializer.ts] ////

=== arrayLiteralInOperatorInForInitializer.ts ===
// The `in` operator is allowed in an array literal that appears in the head of
// a `for` statement: the for head's [~In] parameter does not reach into
// array literals (ElementList : AssignmentExpression[+In]).

const o = { a: 1 };
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))
>a : Symbol(a, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 11))

const k = "a";
>k : Symbol(k, Decl(arrayLiteralInOperatorInForInitializer.ts, 5, 5))

for (let i = 0, has = [k in o]; i < 1; i++) {
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 7, 8))
>has : Symbol(has, Decl(arrayLiteralInOperatorInForInitializer.ts, 7, 15))
>k : Symbol(k, Decl(arrayLiteralInOperatorInForInitializer.ts, 5, 5))
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 7, 8))
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 7, 8))

console.log(has);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>has : Symbol(has, Decl(arrayLiteralInOperatorInForInitializer.ts, 7, 15))
}

for (let i = 0, has = [k in o, "b" in o, !(k in o)]; i < 1; i++) {
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 11, 8))
>has : Symbol(has, Decl(arrayLiteralInOperatorInForInitializer.ts, 11, 15))
>k : Symbol(k, Decl(arrayLiteralInOperatorInForInitializer.ts, 5, 5))
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))
>k : Symbol(k, Decl(arrayLiteralInOperatorInForInitializer.ts, 5, 5))
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 11, 8))
>i : Symbol(i, Decl(arrayLiteralInOperatorInForInitializer.ts, 11, 8))

console.log(has);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>has : Symbol(has, Decl(arrayLiteralInOperatorInForInitializer.ts, 11, 15))
}

let x: any;
>x : Symbol(x, Decl(arrayLiteralInOperatorInForInitializer.ts, 15, 3))

for ([x = "x" in {}] of [[]]) {
>x : Symbol(x, Decl(arrayLiteralInOperatorInForInitializer.ts, 15, 3))

console.log(x);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x : Symbol(x, Decl(arrayLiteralInOperatorInForInitializer.ts, 15, 3))
}

// The initializer of a `for` statement still ends at `in`, so that `for-in`
// statements keep parsing as before.
for (const key in o) {
>key : Symbol(key, Decl(arrayLiteralInOperatorInForInitializer.ts, 22, 10))
>o : Symbol(o, Decl(arrayLiteralInOperatorInForInitializer.ts, 4, 5))

console.log(key);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>key : Symbol(key, Decl(arrayLiteralInOperatorInForInitializer.ts, 22, 10))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//// [tests/cases/compiler/arrayLiteralInOperatorInForInitializer.ts] ////

=== arrayLiteralInOperatorInForInitializer.ts ===
// The `in` operator is allowed in an array literal that appears in the head of
// a `for` statement: the for head's [~In] parameter does not reach into
// array literals (ElementList : AssignmentExpression[+In]).

const o = { a: 1 };
>o : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1

const k = "a";
>k : "a"
>"a" : "a"

for (let i = 0, has = [k in o]; i < 1; i++) {
>i : number
>0 : 0
>has : boolean[]
>[k in o] : boolean[]
>k in o : boolean
>k : "a"
>o : { a: number; }
>i < 1 : boolean
>i : number
>1 : 1
>i++ : number
>i : number

console.log(has);
>console.log(has) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>has : boolean[]
}

for (let i = 0, has = [k in o, "b" in o, !(k in o)]; i < 1; i++) {
>i : number
>0 : 0
>has : boolean[]
>[k in o, "b" in o, !(k in o)] : boolean[]
>k in o : boolean
>k : "a"
>o : { a: number; }
>"b" in o : boolean
>"b" : "b"
>o : { a: number; }
>!(k in o) : boolean
>(k in o) : boolean
>k in o : boolean
>k : "a"
>o : { a: number; }
>i < 1 : boolean
>i : number
>1 : 1
>i++ : number
>i : number

console.log(has);
>console.log(has) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>has : boolean[]
}

let x: any;
>x : any

for ([x = "x" in {}] of [[]]) {
>[x = "x" in {}] : [boolean]
>x = "x" in {} : boolean
>x : any
>"x" in {} : boolean
>"x" : "x"
>{} : {}
>[[]] : undefined[][]
>[] : undefined[]

console.log(x);
>console.log(x) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>x : any
}

// The initializer of a `for` statement still ends at `in`, so that `for-in`
// statements keep parsing as before.
for (const key in o) {
>key : string
>o : { a: number; }

console.log(key);
>console.log(key) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>key : string
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @target: esnext
// @strict: false

// The `in` operator is allowed in an array literal that appears in the head of
// a `for` statement: the for head's [~In] parameter does not reach into
// array literals (ElementList : AssignmentExpression[+In]).

const o = { a: 1 };
const k = "a";

for (let i = 0, has = [k in o]; i < 1; i++) {
console.log(has);
}

for (let i = 0, has = [k in o, "b" in o, !(k in o)]; i < 1; i++) {
console.log(has);
}

let x: any;
for ([x = "x" in {}] of [[]]) {
console.log(x);
}

// The initializer of a `for` statement still ends at `in`, so that `for-in`
// statements keep parsing as before.
for (const key in o) {
console.log(key);
}
Loading