diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.kt b/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.kt new file mode 100644 index 00000000000..0d63a37f396 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.kt @@ -0,0 +1,8 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo(x: Any) { + js("delete x.foo;") + js("delete x['bar'];") + js("delete x.baz();") + js("delete this;") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.txt b/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.txt new file mode 100644 index 00000000000..199e30b63e6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.txt @@ -0,0 +1,3 @@ +package + +public fun foo(/*0*/ x: kotlin.Any): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index 0e62b5bdb38..dd2b81ba1da 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -368,6 +368,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes doTest(fileName); } + @TestMetadata("deleteOperation.kt") + public void testDeleteOperation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jsCode/deleteOperation.kt"); + doTest(fileName); + } + @TestMetadata("error.kt") public void testError() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jsCode/error.kt"); diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java index 5893b4f2dc5..9f8a10069c0 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java +++ b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java @@ -392,9 +392,7 @@ public class JsAstMapper { JsUnaryOperator.DELETE, to); } else { - throw createParserException( - "'delete' can only operate on property names and array elements", - from); + return new JsNullLiteral(); } } diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/MessagesBundle.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/MessagesBundle.java index 7a9e976b7c2..dfe4d5f189a 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/MessagesBundle.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/MessagesBundle.java @@ -81,5 +81,7 @@ public class MessagesBundle extends ListResourceBundle { {"msg.catch.unreachable", "any catch clauses following an unqualified catch are unreachable"}, {"msg.no.name.after.dot", "missing name after . operator"}, {"msg.jsni.expected.identifier", "Expected an identifier in JSNI reference"}, + {"msg.wrong.delete argument", "Wrong argument for ''delete'' operation. " + + "Must be either property reference or array subscript expression."}, }; } \ No newline at end of file diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java index ec226b44311..b8b7562f7c4 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java @@ -37,6 +37,8 @@ package com.google.gwt.dev.js.rhino; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -890,8 +892,13 @@ public class Parser { case TokenStream.DEC: return nf.createUnary(tt, TokenStream.PRE, memberExpr(ts, true), position); - case TokenStream.DELPROP: - return nf.createUnary(TokenStream.DELPROP, unaryExpr(ts), position); + case TokenStream.DELPROP: { + Node argument = unaryExpr(ts); + if (!isValidDeleteArgument(argument)) { + Context.reportError("msg.wrong.delete argument", argument.getPosition(), ts.lastPosition); + } + return nf.createUnary(TokenStream.DELPROP, argument, position); + } case TokenStream.ERROR: break; @@ -922,6 +929,10 @@ public class Parser { return nf.createName("err", position); // Only reached on error. Try to continue. } + private static boolean isValidDeleteArgument(@NotNull Node node) { + return node.type == TokenStream.GETPROP || node.type == TokenStream.GETELEM; + } + private Node argumentList(TokenStream ts, Node listNode) throws IOException, JavaScriptException { boolean matched; ts.flags |= TokenStream.TSF_REGEXP;