Mercurial > hg > jdk9-shenandoah > nashorn
changeset 1360:b983e998f528
8131683: Delete fails over multiple scopes
Reviewed-by: mhaupt, sundar
author | hannesw |
---|---|
date | Wed, 22 Jul 2015 10:18:33 +0200 |
parents | 348ce347ba14 |
children | b27730a502c3 |
files | src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java test/script/basic/JDK-8131683.js test/script/basic/JDK-8131683.js.EXPECTED |
diffstat | 5 files changed, 139 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Mon Jul 20 13:11:26 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Jul 22 10:18:33 2015 +0200 @@ -783,12 +783,13 @@ // If this is a declared variable or a function parameter, delete always fails (except for globals). final String name = ident.getName(); final Symbol symbol = ident.getSymbol(); - final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); - if (failDelete && symbol.isThis()) { + if (symbol.isThis()) { + // Can't delete "this", ignore and return true return LiteralNode.newInstance(unaryNode, true).accept(this); } final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); + final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); if (!failDelete) { args.add(compilerConstantIdentifier(SCOPE)); @@ -798,6 +799,8 @@ if (failDelete) { request = Request.FAIL_DELETE; + } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) { + request = Request.SLOW_DELETE; } } else if (rhs instanceof AccessNode) { final Expression base = ((AccessNode)rhs).getBase();
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Mon Jul 20 13:11:26 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Wed Jul 22 10:18:33 2015 +0200 @@ -56,6 +56,8 @@ REFERENCE_ERROR, /** Delete operator */ DELETE(TokenType.DELETE, Type.BOOLEAN, 1), + /** Delete operator for slow scopes */ + SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** Delete operator that always fails -- see Lower */ FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** === operator with at least one object */
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Mon Jul 20 13:11:26 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 22 10:18:33 2015 +0200 @@ -685,6 +685,33 @@ } /** + * ECMA 11.4.1 - delete operator, implementation for slow scopes + * + * This implementation of 'delete' walks the scope chain to find the scope that contains the + * property to be deleted, then invokes delete on it. + * + * @param obj top scope object + * @param property property to delete + * @param strict are we in strict mode + * + * @return true if property was successfully found and deleted + */ + public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) { + if (obj instanceof ScriptObject) { + ScriptObject sobj = (ScriptObject) obj; + final String key = property.toString(); + while (sobj != null && sobj.isScope()) { + final FindProperty find = sobj.findProperty(key, false); + if (find != null) { + return sobj.delete(key, Boolean.TRUE.equals(strict)); + } + sobj = sobj.getProto(); + } + } + return DELETE(obj, property, strict); + } + + /** * ECMA 11.4.1 - delete operator, special case * * This is 'delete' that always fails. We have to check strict mode and throw error.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8131683.js Wed Jul 22 10:18:33 2015 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, 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. + */ + +/** + * JDK-8131683: Delete fails over multiple scopes + * + * @test + * @run + */ + +a = 1; +b = 2; +c = 3; + +var A = 1; +var B = 2; +var C = 3; +function D() {} + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete a; +})()); + +print((function() { + eval(""); + return delete b; +})()); + +print((function() { + return eval("delete c"); +})()); + +print((function() { + eval("d = 4"); + return eval("delete d"); +})()); + +print(typeof a); +print(typeof b); +print(typeof c); +print(typeof d); + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete A; +})()); + +print((function() { + eval(""); + return delete B; +})()); + +print((function() { + return eval("delete C"); +})()); + +print((function() { + eval(""); + return delete D; +})()); + +print(typeof A); +print(typeof B); +print(typeof C); +print(typeof D); +