--- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java 2016-11-11 07:32:29.315488843 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java 2016-11-11 07:32:29.176476083 -0800 @@ -384,7 +384,7 @@ final List catchTrees = new ArrayList<>(catchNodes.size()); for (final CatchNode catchNode : catchNodes) { catchTrees.add(new CatchTreeImpl(catchNode, - translateIdent(catchNode.getException()), + translateExpr(catchNode.getException()), (BlockTree) translateBlock(catchNode.getBody()), translateExpr(catchNode.getExceptionCondition()))); } --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java 2016-11-11 07:32:30.001551814 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java 2016-11-11 07:32:29.860538871 -0800 @@ -462,7 +462,7 @@ @Override public boolean enterCatchNode(final CatchNode catchNode) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = catchNode.getExceptionIdentifier(); final Block block = lc.getCurrentBlock(); start(catchNode); --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-11-11 07:32:30.764621853 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-11-11 07:32:30.621608726 -0800 @@ -3255,7 +3255,7 @@ enterBlock(catchBlock); final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0); - final IdentNode exception = catchNode.getException(); + final IdentNode exception = catchNode.getExceptionIdentifier(); final Expression exceptionCondition = catchNode.getExceptionCondition(); final Block catchBody = catchNode.getBody(); --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java 2016-11-11 07:32:31.636701898 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java 2016-11-11 07:32:31.484687945 -0800 @@ -1033,7 +1033,7 @@ joinOnLabel(catchLabel); for(final CatchNode catchNode: tryNode.getCatches()) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = catchNode.getExceptionIdentifier(); onAssignment(exception, LvarType.OBJECT); final Expression condition = catchNode.getExceptionCondition(); if(condition != null) { --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java 2016-11-11 07:32:32.379770101 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java 2016-11-11 07:32:32.247757984 -0800 @@ -176,6 +176,15 @@ public Node leaveCallNode(final CallNode callNode) { return checkEval(callNode.setFunction(markerFunction(callNode.getFunction()))); } + + @Override + public boolean enterCatchNode(final CatchNode catchNode) { + Expression exception = catchNode.getException(); + if ((exception != null) && !(exception instanceof IdentNode)) { + throwNotImplementedYet("es6.destructuring", exception); + } + return true; + } @Override public Node leaveCatchNode(final CatchNode catchNode) { --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java 2016-11-11 07:32:33.101836377 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java 2016-11-11 07:32:32.955822975 -0800 @@ -35,8 +35,8 @@ public final class CatchNode extends Statement { private static final long serialVersionUID = 1L; - /** Exception identifier. */ - private final IdentNode exception; + /** Exception binding identifier or binding pattern. */ + private final Expression exception; /** Exception condition. */ private final Expression exceptionCondition; @@ -52,21 +52,27 @@ * @param lineNumber lineNumber * @param token token * @param finish finish - * @param exception variable name of exception + * @param exception variable name or pattern of exception * @param exceptionCondition exception condition * @param body catch body * @param isSyntheticRethrow true if this node is a synthetically generated rethrow node. */ - public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, + public CatchNode(final int lineNumber, final long token, final int finish, final Expression exception, final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) { super(lineNumber, token, finish); - this.exception = exception == null ? null : exception.setIsInitializedHere(); + if (exception instanceof IdentNode) { + this.exception = ((IdentNode) exception).setIsInitializedHere(); + } else if ((exception instanceof LiteralNode) || (exception instanceof ObjectNode)) { + this.exception = exception; + } else { + throw new IllegalArgumentException("invalid catch parameter"); + } this.exceptionCondition = exceptionCondition; - this.body = body; + this.body = body; this.isSyntheticRethrow = isSyntheticRethrow; } - private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition, + private CatchNode(final CatchNode catchNode, final Expression exception, final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) { super(catchNode); this.exception = exception; @@ -83,11 +89,10 @@ public Node accept(final NodeVisitor visitor) { if (visitor.enterCatchNode(this)) { return visitor.leaveCatchNode( - setException((IdentNode)exception.accept(visitor)). - setExceptionCondition(exceptionCondition == null ? null : (Expression)exceptionCondition.accept(visitor)). - setBody((Block)body.accept(visitor))); + setException((Expression) exception.accept(visitor)). + setExceptionCondition(exceptionCondition == null ? null : (Expression) exceptionCondition.accept(visitor)). + setBody((Block) body.accept(visitor))); } - return this; } @@ -109,11 +114,22 @@ } /** + * Get the binding pattern representing the exception thrown + * + * @return the exception binding pattern + */ + public Expression getException() { + return exception; + } + + /** * Get the identifier representing the exception thrown + * * @return the exception identifier + * @throws ClassCastException if exception set is not binding identifier */ - public IdentNode getException() { - return exception; + public IdentNode getExceptionIdentifier() { + return (IdentNode) exception; } /** @@ -146,16 +162,22 @@ /** * Resets the exception of a catch block - * @param exception new exception + * + * @param exception new exception which can be binding identifier or binding + * pattern * @return new catch node if changed, same otherwise */ - public CatchNode setException(final IdentNode exception) { + public CatchNode setException(final Expression exception) { if (this.exception == exception) { return this; } + /*check if exception is legitimate*/ + if (!((exception instanceof IdentNode) || (exception instanceof LiteralNode) || (exception instanceof ObjectNode))) { + throw new IllegalArgumentException("invalid catch parameter"); + } return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow); } - + private CatchNode setBody(final Block body) { if (this.body == body) { return this; --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java 2016-11-11 07:32:33.842904397 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java 2016-11-11 07:32:33.711892372 -0800 @@ -2619,13 +2619,23 @@ next(); expect(LPAREN); - // FIXME: ES6 catch parameter can be a BindingIdentifier or a BindingPattern - // We need to generalize this here! + // ES6 catch parameter can be a BindingIdentifier or a BindingPattern // http://www.ecma-international.org/ecma-262/6.0/ - final IdentNode exception = getIdent(); + final String contextString = "catch argument"; + final Expression exception = bindingIdentifierOrPattern(contextString); + final boolean isDestructuring = !(exception instanceof IdentNode); + if (isDestructuring) { + verifyDestructuringBindingPattern(exception, new Consumer() { + @Override + public void accept(final IdentNode identNode) { + verifyIdent(identNode, contextString); + } + }); + } else { + // ECMA 12.4.1 strict mode restrictions + verifyStrictIdent((IdentNode) exception, "catch argument"); + } - // ECMA 12.4.1 strict mode restrictions - verifyStrictIdent(exception, "catch argument"); // Nashorn extension: catch clause can have optional // condition. So, a single try can have more than one --- old/test/script/basic/es6/destructuring.js 2016-11-11 07:32:34.701983248 -0800 +++ new/test/script/basic/es6/destructuring.js 2016-11-11 07:32:34.540968469 -0800 @@ -62,4 +62,11 @@ check("(function([x]) { return x; })()"); check("for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ;"); check("for ([ arrow = () => {} ] of [[]]) ;"); +check("try { throw null;} catch({}) { }"); +check("try { throw {} } catch ({}) { }"); +check("try { throw [] } catch ([,]) { }"); +check("try { throw { w: [7, undefined, ] }} catch ({ w: [x, y, z] = [4, 5, 6] }) { }"); +check("try { throw { a: 2, b: 3} } catch ({a, b}) { }"); +check("try { throw [null] } catch ([[x]]) { }"); +check("try { throw { w: undefined } } catch ({ w: { x, y, z } = { x: 4, y: 5, z: 6 } }) { }"); --- old/test/script/basic/es6/destructuring.js.EXPECTED 2016-11-11 07:32:35.382045668 -0800 +++ new/test/script/basic/es6/destructuring.js.EXPECTED 2016-11-11 07:32:35.259034378 -0800 @@ -70,3 +70,24 @@ java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:0 ES6 destructuring is not yet implemented for ([ arrow = () => {} ] of [[]]) ; ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:25 ES6 destructuring is not yet implemented +try { throw null;} catch({}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:24 ES6 destructuring is not yet implemented +try { throw {} } catch ({}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:24 ES6 destructuring is not yet implemented +try { throw [] } catch ([,]) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:44 ES6 destructuring is not yet implemented +try { throw { w: [7, undefined, ] }} catch ({ w: [x, y, z] = [4, 5, 6] }) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:35 ES6 destructuring is not yet implemented +try { throw { a: 2, b: 3} } catch ({a, b}) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:28 ES6 destructuring is not yet implemented +try { throw [null] } catch ([[x]]) { } + ^ +java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6:1:38 ES6 destructuring is not yet implemented +try { throw { w: undefined } } catch ({ w: { x, y, z } = { x: 4, y: 5, z: 6 } }) { } + ^ --- /dev/null 2016-04-23 11:38:21.039000000 -0700 +++ new/test/script/nosecurity/treeapi/destructuring_catch.js 2016-11-11 07:32:35.941096982 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Tests to check representation of ES6 catch parameter as binding pattern. + * + * @test + * @option -scripting + * @run + */ + +load(__DIR__ + "utils.js") + +var code = <