Mon, 25 Feb 2013 16:51:04 +0100
8006984: Introducing local into a function inside with statement confuses its scope
Reviewed-by: jlaskey, lagergren, sundar
1.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Mon Feb 25 18:13:23 2013 +0530 1.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Mon Feb 25 16:51:04 2013 +0100 1.3 @@ -628,14 +628,15 @@ 1.4 * @return FindPropertyData or null if not found. 1.5 */ 1.6 public final FindProperty findProperty(final String key, final boolean deep) { 1.7 - return findProperty(key, deep, false); 1.8 + return findProperty(key, deep, false, this); 1.9 } 1.10 1.11 /** 1.12 * Low level property API (not using property descriptors) 1.13 * <p> 1.14 - * Find a property in the prototype hierarchy. Note: this is final and not 1.15 - * a good idea to override. If you have to, use 1.16 + * Find a property in the prototype hierarchy. Note: this is not a good idea 1.17 + * to override except as it was done in {@link WithObject}. 1.18 + * If you have to, use 1.19 * {jdk.nashorn.internal.objects.NativeArray{@link #getProperty(String)} or 1.20 * {jdk.nashorn.internal.objects.NativeArray{@link #getPropertyDescriptor(String)} as the 1.21 * overriding way to find array properties 1.22 @@ -645,27 +646,29 @@ 1.23 * @param key Property key. 1.24 * @param deep Whether the search should look up proto chain. 1.25 * @param stopOnNonScope should a deep search stop on the first non-scope object? 1.26 + * @param start the object on which the lookup was originally initiated 1.27 * 1.28 * @return FindPropertyData or null if not found. 1.29 */ 1.30 - public final FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope) { 1.31 - for (ScriptObject self = this; self != null; self = self.getProto()) { 1.32 - // if doing deep search, stop search on the first non-scope object if asked to do so 1.33 - if (stopOnNonScope && self != this && !self.isScope()) { 1.34 - return null; 1.35 + FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { 1.36 + // if doing deep search, stop search on the first non-scope object if asked to do so 1.37 + if (stopOnNonScope && start != this && !isScope()) { 1.38 + return null; 1.39 + } 1.40 + 1.41 + final PropertyMap selfMap = getMap(); 1.42 + final Property property = selfMap.findProperty(key); 1.43 + 1.44 + if (property != null) { 1.45 + return new FindProperty(start, this, property); 1.46 + } 1.47 + 1.48 + if (deep) { 1.49 + final ScriptObject proto = getProto(); 1.50 + if(proto != null) { 1.51 + return proto.findProperty(key, deep, stopOnNonScope, start); 1.52 } 1.53 - 1.54 - final PropertyMap selfMap = self.getMap(); 1.55 - final Property property = selfMap.findProperty(key); 1.56 - 1.57 - if (property != null) { 1.58 - return new FindProperty(this, self, property); 1.59 - } 1.60 - 1.61 - if (!deep) { 1.62 - return null; 1.63 - } 1.64 - } 1.65 + } 1.66 1.67 return null; 1.68 } 1.69 @@ -1781,12 +1784,12 @@ 1.70 final boolean scope = isScope(); 1.71 /* 1.72 * If doing property set on a scope object, we should stop proto search on the first 1.73 - * non-scope object. Without this, for exmaple, when assigning "toString" on global scope, 1.74 + * non-scope object. Without this, for example, when assigning "toString" on global scope, 1.75 * we'll end up assigning it on it's proto - which is Object.prototype.toString !! 1.76 * 1.77 * toString = function() { print("global toString"); } // don't affect Object.prototype.toString 1.78 */ 1.79 - FindProperty find = findProperty(name, true, scope); 1.80 + FindProperty find = findProperty(name, true, scope, this); 1.81 // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors. 1.82 if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 1.83 // We should still check if inherited data property is not writable
2.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java Mon Feb 25 18:13:23 2013 +0530 2.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Mon Feb 25 16:51:04 2013 +0100 2.3 @@ -184,6 +184,28 @@ 2.4 return null; 2.5 } 2.6 2.7 + /** 2.8 + * Overridden to try to find the property first in the expression object (and its prototypes), and only then in this 2.9 + * object (and its prototypes). 2.10 + * 2.11 + * @param key Property key. 2.12 + * @param deep Whether the search should look up proto chain. 2.13 + * @param stopOnNonScope should a deep search stop on the first non-scope object? 2.14 + * @param start the object on which the lookup was originally initiated 2.15 + * 2.16 + * @return FindPropertyData or null if not found. 2.17 + */ 2.18 + @Override 2.19 + FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { 2.20 + if (expression instanceof ScriptObject) { 2.21 + final FindProperty exprProperty = ((ScriptObject)expression).findProperty(key, deep, stopOnNonScope, start); 2.22 + if(exprProperty != null) { 2.23 + return exprProperty; 2.24 + } 2.25 + } 2.26 + return super.findProperty(key, deep, stopOnNonScope, start); 2.27 + } 2.28 + 2.29 @Override 2.30 public void setSplitState(final int state) { 2.31 getNonWithParent().setSplitState(state);
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8006984.js Mon Feb 25 16:51:04 2013 +0100 3.3 @@ -0,0 +1,44 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * findProperty on WithObject was not considering its object argument 3.29 + * 3.30 + * @test 3.31 + * @run 3.32 + */ 3.33 + 3.34 +var guiPkgs = { JFrame: function() { print("created"); } }; 3.35 + 3.36 +with (guiPkgs) { 3.37 + var main = function() { 3.38 + var frame; // <---- this local variable caused scope to be not set properly prior to fix 3.39 + 3.40 + function createFrame() { 3.41 + frame = new JFrame(); 3.42 + } 3.43 + 3.44 + createFrame(); 3.45 + } 3.46 +} 3.47 +main();
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/script/basic/JDK-8006984.js.EXPECTED Mon Feb 25 16:51:04 2013 +0100 4.3 @@ -0,0 +1,1 @@ 4.4 +created