diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 86a08a03fea..88b773ec608 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -2220,7 +2220,7 @@ public class TypeScriptASTConverter { * ObjectExpression} with {@link ObjectPattern} and {@link SpreadElement} with {@link * RestElement}. */ - private Expression convertLValue(Expression e) { + private Expression convertLValue(Expression e) throws ParseError { if (e == null) return null; SourceLocation loc = e.getLoc(); @@ -2249,8 +2249,14 @@ public class TypeScriptASTConverter { if (e instanceof ParenthesizedExpression) return new ParenthesizedExpression( loc, convertLValue(((ParenthesizedExpression) e).getExpression())); - if (e instanceof SpreadElement) - return new RestElement(e.getLoc(), convertLValue(((SpreadElement) e).getArgument())); + if (e instanceof SpreadElement) { + Expression argument = convertLValue(((SpreadElement) e).getArgument()); + if (argument instanceof AssignmentPattern) { + throw new ParseError( + "Rest patterns cannot have a default value", argument.getLoc().getStart()); + } + return new RestElement(e.getLoc(), argument); + } return e; } diff --git a/javascript/extractor/tests/ts/input/restPatternWithDefault.ts b/javascript/extractor/tests/ts/input/restPatternWithDefault.ts new file mode 100644 index 00000000000..f5792435ff7 --- /dev/null +++ b/javascript/extractor/tests/ts/input/restPatternWithDefault.ts @@ -0,0 +1,3 @@ +var a: number[]; +var x: number[]; +[...x = a] = a; // Error, rest element cannot have initializer diff --git a/javascript/extractor/tests/ts/output/trap/restPatternWithDefault.ts.trap b/javascript/extractor/tests/ts/output/trap/restPatternWithDefault.ts.trap new file mode 100644 index 00000000000..a375f4637f6 --- /dev/null +++ b/javascript/extractor/tests/ts/output/trap/restPatternWithDefault.ts.trap @@ -0,0 +1,42 @@ +#10000=@"/restPatternWithDefault.ts;sourcefile" +files(#10000,"/restPatternWithDefault.ts","restPatternWithDefault","ts",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +toplevels(#20001,0) +#20002=@"loc,{#10000},1,1,1,1" +locations_default(#20002,#10000,1,1,1,1) +hasLocation(#20001,#20002) +#20003=* +jsParseErrors(#20003,#20001,"Error: Rest patterns cannot have a default value","[...x = a] = a; // Error, rest element cannot have initializer +") +#20004=@"loc,{#10000},3,5,3,5" +locations_default(#20004,#10000,3,5,3,5) +hasLocation(#20003,#20004) +#20005=* +lines(#20005,#20001,"var a: number[];"," +") +#20006=@"loc,{#10000},1,1,1,16" +locations_default(#20006,#10000,1,1,1,16) +hasLocation(#20005,#20006) +#20007=* +lines(#20007,#20001,"var x: number[];"," +") +#20008=@"loc,{#10000},2,1,2,16" +locations_default(#20008,#10000,2,1,2,16) +hasLocation(#20007,#20008) +#20009=* +lines(#20009,#20001,"[...x = a] = a; // Error, rest element cannot have initializer"," +") +#20010=@"loc,{#10000},3,1,3,63" +locations_default(#20010,#10000,3,1,3,63) +hasLocation(#20009,#20010) +numlines(#20001,3,0,0) +numlines(#10000,3,0,0) +filetype(#10000,"typescript")