--- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java 2016-11-10 02:56:14.309279940 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java 2016-11-10 02:56:14.177267821 -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-10 02:56:14.961339799 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java 2016-11-10 02:56:14.843328966 -0800 @@ -462,7 +462,7 @@ @Override public boolean enterCatchNode(final CatchNode catchNode) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = (IdentNode) catchNode.getException(); final Block block = lc.getCurrentBlock(); start(catchNode); --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-11-10 02:56:15.664404341 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-11-10 02:56:15.521391213 -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 = (IdentNode) catchNode.getException(); 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-10 02:56:16.488479992 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java 2016-11-10 02:56:16.342466588 -0800 @@ -1033,7 +1033,7 @@ joinOnLabel(catchLabel); for(final CatchNode catchNode: tryNode.getCatches()) { - final IdentNode exception = catchNode.getException(); + final IdentNode exception = (IdentNode) catchNode.getException(); 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-10 02:56:17.173542881 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java 2016-11-10 02:56:17.035530212 -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-10 02:56:17.843604394 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CatchNode.java 2016-11-10 02:56:17.704591632 -0800 @@ -35,8 +35,8 @@ public final class CatchNode extends Statement { private static final long serialVersionUID = 1L; - /** Exception identifier. */ - private final IdentNode exception; + /** Exception identifier or pattern. */ + private final Expression exception; /** Exception condition. */ private final Expression exceptionCondition; @@ -52,21 +52,26 @@ * @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 { + this.exception = exception; + } + 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 +88,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; } @@ -112,7 +116,7 @@ * Get the identifier representing the exception thrown * @return the exception identifier */ - public IdentNode getException() { + public Expression getException() { return exception; } @@ -149,7 +153,7 @@ * @param exception new exception * @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; } --- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java 2016-11-10 02:56:18.491663886 -0800 +++ new/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java 2016-11-10 02:56:18.351651033 -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-10 02:56:19.219730723 -0800 +++ new/test/script/basic/es6/destructuring.js 2016-11-10 02:56:19.109720624 -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-10 02:56:19.867790215 -0800 +++ new/test/script/basic/es6/destructuring.js.EXPECTED 2016-11-10 02:56:19.744778923 -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 } }) { } + ^