8027700: function redeclaration checks missing for declaration binding instantiation
Reviewed-by: jlaskey, lagergren
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Fri Nov 01 19:54:48 2013 +0530
@@ -271,6 +271,7 @@
functionNode.addDeclaredSymbol(symbol);
if (varNode.isFunctionDeclaration()) {
newType(symbol, FunctionNode.FUNCTION_TYPE);
+ symbol.setIsFunctionDeclaration();
}
return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java Fri Nov 01 19:54:48 2013 +0530
@@ -134,6 +134,10 @@
flags |= Property.CAN_BE_UNDEFINED;
}
+ if (symbol.isFunctionDeclaration()) {
+ flags |= Property.IS_FUNCTION_DECLARATION;
+ }
+
return flags;
}
--- a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java Fri Nov 01 19:54:48 2013 +0530
@@ -75,6 +75,8 @@
public static final int IS_SPECIALIZED_PARAM = 1 << 13;
/** Is this symbol a shared temporary? */
public static final int IS_SHARED = 1 << 14;
+ /** Is this a function declaration? */
+ public static final int IS_FUNCTION_DECLARATION = 1 << 15;
/** Null or name identifying symbol. */
private final String name;
@@ -360,6 +362,14 @@
}
/**
+ * Check if this symbol is a function declaration
+ * @return true if a function declaration
+ */
+ public boolean isFunctionDeclaration() {
+ return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
+ }
+
+ /**
* Creates an unshared copy of a symbol. The symbol must be currently shared.
* @param newName the name for the new symbol.
* @return a new, unshared symbol.
@@ -396,6 +406,16 @@
/**
+ * Mark this symbol as a function declaration.
+ */
+ public void setIsFunctionDeclaration() {
+ if (!isFunctionDeclaration()) {
+ trace("SET IS FUNCTION DECLARATION");
+ flags |= IS_FUNCTION_DECLARATION;
+ }
+ }
+
+ /**
* Check if this symbol is a variable
* @return true if variable
*/
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java Fri Nov 01 19:54:48 2013 +0530
@@ -56,33 +56,36 @@
public static final int WRITABLE_ENUMERABLE_CONFIGURABLE = 0b0000_0000_0000;
/** ECMA 8.6.1 - Is this property not writable? */
- public static final int NOT_WRITABLE = 0b0000_0000_0001;
+ public static final int NOT_WRITABLE = 1 << 0;
/** ECMA 8.6.1 - Is this property not enumerable? */
- public static final int NOT_ENUMERABLE = 0b0000_0000_0010;
+ public static final int NOT_ENUMERABLE = 1 << 1;
/** ECMA 8.6.1 - Is this property not configurable? */
- public static final int NOT_CONFIGURABLE = 0b0000_0000_0100;
+ public static final int NOT_CONFIGURABLE = 1 << 2;
- private static final int MODIFY_MASK = 0b0000_0000_1111;
+ private static final int MODIFY_MASK = (NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE);
/** Is this a spill property? See {@link AccessorProperty} */
- public static final int IS_SPILL = 0b0000_0001_0000;
+ public static final int IS_SPILL = 1 << 3;
/** Is this a function parameter? */
- public static final int IS_PARAMETER = 0b0000_0010_0000;
+ public static final int IS_PARAMETER = 1 << 4;
/** Is parameter accessed thru arguments? */
- public static final int HAS_ARGUMENTS = 0b0000_0100_0000;
+ public static final int HAS_ARGUMENTS = 1 << 5;
/** Is this property always represented as an Object? See {@link ObjectClassGenerator} and dual fields flag. */
- public static final int IS_ALWAYS_OBJECT = 0b0000_1000_0000;
+ public static final int IS_ALWAYS_OBJECT = 1 << 6;
/** Can this property be primitive? */
- public static final int CAN_BE_PRIMITIVE = 0b0001_0000_0000;
+ public static final int CAN_BE_PRIMITIVE = 1 << 7;
/** Can this property be undefined? */
- public static final int CAN_BE_UNDEFINED = 0b0010_0000_0000;
+ public static final int CAN_BE_UNDEFINED = 1 << 8;
+
+ /* Is this a function declaration property ? */
+ public static final int IS_FUNCTION_DECLARATION = 1 << 9;
/** Property key. */
private final String key;
@@ -522,4 +525,12 @@
public boolean canBeUndefined() {
return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED;
}
+
+ /**
+ * Check whether this property represents a function declaration.
+ * @return whether this property is a function declaration or not.
+ */
+ public boolean isFunctionDeclaration() {
+ return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
+ }
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Nov 01 19:54:48 2013 +0530
@@ -226,14 +226,23 @@
for (final Property property : properties) {
final String key = property.getKey();
-
- if (newMap.findProperty(key) == null) {
+ final Property oldProp = newMap.findProperty(key);
+ if (oldProp == null) {
if (property instanceof UserAccessorProperty) {
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
newMap = newMap.addProperty(prop);
} else {
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
}
+ } else {
+ // See ECMA section 10.5 Declaration Binding Instantiation
+ // step 5 processing each function declaration.
+ if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
+ if (oldProp instanceof UserAccessorProperty ||
+ !(oldProp.isWritable() && oldProp.isEnumerable())) {
+ throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
+ }
+ }
}
}
--- a/nashorn/test/script/basic/JDK-8015355.js Wed Oct 30 20:09:44 2013 +0530
+++ b/nashorn/test/script/basic/JDK-8015355.js Fri Nov 01 19:54:48 2013 +0530
@@ -28,10 +28,6 @@
* @run
*/
-function fail(msg) {
- print(msg);
-}
-
function check(callback) {
try {
callback();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8027700.js Fri Nov 01 19:54:48 2013 +0530
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010, 2013, 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-8027700: function redeclaration checks missing for declaration binding instantiation
+ *
+ * @test
+ * @run
+ */
+
+Object.defineProperty(this,"x", {
+ value:0,
+ writable:true,
+ enumerable:false
+})
+
+try {
+ eval("function x() {}");
+ fail("should have thrown TypeError");
+} catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("TypeError expected but got " + e);
+ }
+}
+
+Object.defineProperty(this, "foo", { value:0 })
+try {
+ eval("function foo() {}");
+ fail("should have thrown TypeError");
+} catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("TypeError expected but got " + e);
+ }
+}