--- old/make/project.properties 2014-08-11 20:02:11.802572972 +0530 +++ new/make/project.properties 2014-08-11 20:02:11.478571363 +0530 @@ -201,7 +201,6 @@ # list of test262 test dirs to be excluded test262-test-sys-prop.test.js.exclude.dir=\ - ${test262.suite.dir}/ch12/12.6/12.6.4/12.6.4-2.js \ ${test262.suite.dir}/intl402/ \ ${test262.suite.dir}/bestPractice/ --- old/src/jdk/nashorn/internal/objects/NativeString.java 2014-08-11 20:02:13.150579661 +0530 +++ new/src/jdk/nashorn/internal/objects/NativeString.java 2014-08-11 20:02:12.874578281 +0530 @@ -39,6 +39,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.Set; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -391,10 +392,12 @@ /** * return a List of own keys associated with the object. * @param all True if to include non-enumerable keys. + * @param nonEnumerable set of non-enumerable properties seen already.Used + * to filter out shadowed, but enumerable properties from proto children. * @return Array of keys. */ @Override - public String[] getOwnKeys(final boolean all) { + protected String[] getOwnKeys(final boolean all, final Set nonEnumerable) { final List keys = new ArrayList<>(); // add string index keys @@ -403,7 +406,7 @@ } // add super class properties - keys.addAll(Arrays.asList(super.getOwnKeys(all))); + keys.addAll(Arrays.asList(super.getOwnKeys(all, nonEnumerable))); return keys.toArray(new String[keys.size()]); } --- old/src/jdk/nashorn/internal/runtime/ScriptObject.java 2014-08-11 20:02:13.958583667 +0530 +++ new/src/jdk/nashorn/internal/runtime/ScriptObject.java 2014-08-11 20:02:13.758582677 +0530 @@ -1324,7 +1324,19 @@ * @param all True if to include non-enumerable keys. * @return Array of keys. */ - public String[] getOwnKeys(final boolean all) { + public final String[] getOwnKeys(final boolean all) { + return getOwnKeys(all, null); + } + + /** + * return an array of own property keys associated with the object. + * + * @param all True if to include non-enumerable keys. + * @param nonEnumerable set of non-enumerable properties seen already.Used + to filter out shadowed, but enumerable properties from proto children. + * @return Array of keys. + */ + protected String[] getOwnKeys(final boolean all, final Set nonEnumerable) { final List keys = new ArrayList<>(); final PropertyMap selfMap = this.getMap(); @@ -1338,8 +1350,21 @@ } for (final Property property : selfMap.getProperties()) { - if (all || property.isEnumerable()) { - keys.add(property.getKey()); + final boolean enumerable = property.isEnumerable(); + final String key = property.getKey(); + if (all) { + keys.add(key); + } else if (enumerable) { + // either we don't have non-enumerable filter set or filter set + // does not contain the current property. + if (nonEnumerable == null || !nonEnumerable.contains(key)) { + keys.add(key); + } + } else { + // store this non-enumerable property for later proto walk + if (nonEnumerable != null) { + nonEnumerable.add(key); + } } } @@ -2398,8 +2423,9 @@ @Override protected void init() { final Set keys = new LinkedHashSet<>(); + final Set nonEnumerable = new HashSet<>(); for (ScriptObject self = object; self != null; self = self.getProto()) { - keys.addAll(Arrays.asList(self.getOwnKeys(false))); + keys.addAll(Arrays.asList(self.getOwnKeys(false, nonEnumerable))); } this.values = keys.toArray(new String[keys.size()]); } @@ -2413,8 +2439,9 @@ @Override protected void init() { final ArrayList valueList = new ArrayList<>(); + final Set nonEnumerable = new HashSet<>(); for (ScriptObject self = object; self != null; self = self.getProto()) { - for (final String key : self.getOwnKeys(false)) { + for (final String key : self.getOwnKeys(false, nonEnumerable)) { valueList.add(self.get(key)); } } --- /dev/null 2014-08-11 13:56:20.275712913 +0530 +++ new/test/script/basic/JDK-8054503.js 2014-08-11 20:02:15.118589411 +0530 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * 8054503: test/script/external/test262/test/suite/ch12/12.6/12.6.4/12.6.4-2.js fails with tip + * + * @test + * @run + */ + +function MyFunc() {} + +MyFunc.prototype.foo = 42; +var obj = new MyFunc(); +Object.defineProperty(obj, "foo", { + value: "hello", + enumerable: false +}); + +for (var p in obj) { + if (p == "foo") { + fail("'foo' is not expected here!"); + } +} + +for each (var p in obj) { + if (p == "hello" || p == 42) { + fail("'foo' value is not expected here"); + } +}