8047764: Indexed or polymorphic set on global affects Object.prototype
authorhannesw
Mon, 22 Sep 2014 13:28:28 +0200
changeset 26765 97501edd2979
parent 26764 c777787a937d
child 26766 523242aab20f
8047764: Indexed or polymorphic set on global affects Object.prototype Reviewed-by: lagergren, attila
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ECMAException.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyAccess.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
nashorn/test/script/basic/JDK-8047764-strict.js
nashorn/test/script/basic/JDK-8047764-strict.js.EXPECTED
nashorn/test/script/basic/JDK-8047764.js
nashorn/test/script/basic/JDK-8047764.js.EXPECTED
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Mon Sep 22 13:28:28 2014 +0200
@@ -50,6 +50,7 @@
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 
 /**
  * Mirror object that wraps a given Nashorn Script object.
@@ -261,7 +262,7 @@
     public void setSlot(final int index, final Object value) {
         inGlobal(new Callable<Void>() {
             @Override public Void call() {
-                sobj.set(index, unwrap(value, global), strict);
+                sobj.set(index, unwrap(value, global), getCallSiteFlags());
                 return null;
             }
         });
@@ -425,7 +426,7 @@
                 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
                     final Object value = entry.getValue();
                     final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
-                    sobj.set(entry.getKey(), unwrap(modValue, global), strict);
+                    sobj.set(entry.getKey(), unwrap(modValue, global), getCallSiteFlags());
                 }
                 return null;
             }
@@ -756,6 +757,10 @@
         return (obj == ScriptRuntime.UNDEFINED)? null : obj;
     }
 
+    private int getCallSiteFlags() {
+        return strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+    }
+
     // internals only below this.
     private <V> V inGlobal(final Callable<V> callable) {
         final Global oldGlobal = Context.getGlobal();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java	Mon Sep 22 13:28:28 2014 +0200
@@ -228,11 +228,11 @@
     private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
         if (!dest.isFloatArray()) {
             for (int i = 0, j = offset; i < length; i++, j++) {
-                dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), false);
+                dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), 0);
             }
         } else {
             for (int i = 0, j = offset; i < length; i++, j++) {
-                dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), false);
+                dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), 0);
             }
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Mon Sep 22 13:28:28 2014 +0200
@@ -1825,10 +1825,10 @@
 
         // ECMA 15.11.4.2 Error.prototype.name
         // Error.prototype.name = "Error";
-        errorProto.set(NativeError.NAME, "Error", false);
+        errorProto.set(NativeError.NAME, "Error", 0);
         // ECMA 15.11.4.3 Error.prototype.message
         // Error.prototype.message = "";
-        errorProto.set(NativeError.MESSAGE, "", false);
+        errorProto.set(NativeError.MESSAGE, "", 0);
 
         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
@@ -1841,8 +1841,8 @@
     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
-        prototype.set(NativeError.NAME, name, false);
-        prototype.set(NativeError.MESSAGE, "", false);
+        prototype.set(NativeError.NAME, name, 0);
+        prototype.set(NativeError.MESSAGE, "", 0);
         prototype.setInitialProto(errorProto);
         return cons;
     }
@@ -1902,7 +1902,7 @@
     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
         for (final Field f : scriptEnv.getClass().getFields()) {
             try {
-                options.set(f.getName(), f.get(scriptEnv), false);
+                options.set(f.getName(), f.get(scriptEnv), 0);
             } catch (final IllegalArgumentException | IllegalAccessException exp) {
                 throw new RuntimeException(exp);
             }
@@ -2046,7 +2046,7 @@
         // <anon-function>
         builtinFunction.setInitialProto(anon);
         builtinFunction.setPrototype(anon);
-        anon.set("constructor", builtinFunction, false);
+        anon.set("constructor", builtinFunction, 0);
         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
 
         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Mon Sep 22 13:28:28 2014 +0200
@@ -32,6 +32,7 @@
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
 
 import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
@@ -69,6 +70,7 @@
 import jdk.nashorn.internal.runtime.arrays.IteratorAction;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 
 /**
  * Runtime representation of a JavaScript array. NativeArray only holds numeric
@@ -341,7 +343,7 @@
             if (!newWritable) {
                 // make 'length' property not writable
                 final ScriptObject newDesc = Global.newEmptyInstance();
-                newDesc.set(WRITABLE, false, false);
+                newDesc.set(WRITABLE, false, 0);
                 return super.defineOwnProperty("length", newDesc, false);
             }
 
@@ -808,7 +810,7 @@
             final long len = JSType.toUint32(sobj.getLength());
 
             if (len == 0) {
-                sobj.set("length", 0, true);
+                sobj.set("length", 0, CALLSITE_STRICT);
                 return ScriptRuntime.UNDEFINED;
             }
 
@@ -816,7 +818,7 @@
             final Object element = sobj.get(index);
 
             sobj.delete(index, true);
-            sobj.set("length", index, true);
+            sobj.set("length", index, CALLSITE_STRICT);
 
             return element;
         } catch (final ClassCastException | NullPointerException e) {
@@ -844,9 +846,9 @@
 
             long len = JSType.toUint32(sobj.getLength());
             for (final Object element : args) {
-                sobj.set(len++, element, true);
+                sobj.set(len++, element, CALLSITE_STRICT);
             }
-            sobj.set("length", len, true);
+            sobj.set("length", len, CALLSITE_STRICT);
 
             return len;
         } catch (final ClassCastException | NullPointerException e) {
@@ -928,8 +930,8 @@
             }
 
             long len = JSType.toUint32(sobj.getLength());
-            sobj.set(len++, arg, true);
-            sobj.set("length", len, true);
+            sobj.set(len++, arg, CALLSITE_STRICT);
+            sobj.set("length", len, CALLSITE_STRICT);
             return len;
         } catch (final ClassCastException | NullPointerException e) {
             throw typeError("not.an.object", ScriptRuntime.safeToString(self));
@@ -957,14 +959,14 @@
                 final boolean upperExists = sobj.has(upper);
 
                 if (lowerExists && upperExists) {
-                    sobj.set(lower, upperValue, true);
-                    sobj.set(upper, lowerValue, true);
+                    sobj.set(lower, upperValue, CALLSITE_STRICT);
+                    sobj.set(upper, lowerValue, CALLSITE_STRICT);
                 } else if (!lowerExists && upperExists) {
-                    sobj.set(lower, upperValue, true);
+                    sobj.set(lower, upperValue, CALLSITE_STRICT);
                     sobj.delete(upper, true);
                 } else if (lowerExists && !upperExists) {
                     sobj.delete(lower, true);
-                    sobj.set(upper, lowerValue, true);
+                    sobj.set(upper, lowerValue, CALLSITE_STRICT);
                 }
             }
             return sobj;
@@ -1003,7 +1005,7 @@
                 for (long k = 1; k < len; k++) {
                     final boolean hasCurrent = sobj.has(k);
                     if (hasCurrent) {
-                        sobj.set(k - 1, sobj.get(k), true);
+                        sobj.set(k - 1, sobj.get(k), CALLSITE_STRICT);
                     } else if (hasPrevious) {
                         sobj.delete(k - 1, true);
                     }
@@ -1015,7 +1017,7 @@
             len = 0;
         }
 
-        sobj.set("length", len, true);
+        sobj.set("length", len, CALLSITE_STRICT);
 
         return first;
     }
@@ -1226,7 +1228,7 @@
                 final long to   = k + items.length;
 
                 if (sobj.has(from)) {
-                    sobj.set(to, sobj.get(from), true);
+                    sobj.set(to, sobj.get(from), CALLSITE_STRICT);
                 } else {
                     sobj.delete(to, true);
                 }
@@ -1242,7 +1244,7 @@
 
                 if (sobj.has(from)) {
                     final Object fromValue = sobj.get(from);
-                    sobj.set(to, fromValue, true);
+                    sobj.set(to, fromValue, CALLSITE_STRICT);
                 } else {
                     sobj.delete(to, true);
                 }
@@ -1251,11 +1253,11 @@
 
         long k = start;
         for (int i = 0; i < items.length; i++, k++) {
-            sobj.set(k, items[i], true);
+            sobj.set(k, items[i], CALLSITE_STRICT);
         }
 
         final long newLength = len - deleteCount + items.length;
-        sobj.set("length", newLength, true);
+        sobj.set("length", newLength, CALLSITE_STRICT);
 
         return array;
     }
@@ -1295,19 +1297,19 @@
 
                 if (sobj.has(from)) {
                     final Object fromValue = sobj.get(from);
-                    sobj.set(to, fromValue, true);
+                    sobj.set(to, fromValue, CALLSITE_STRICT);
                 } else {
                     sobj.delete(to, true);
                 }
             }
 
             for (int j = 0; j < items.length; j++) {
-                sobj.set(j, items[j], true);
+                sobj.set(j, items[j], CALLSITE_STRICT);
             }
         }
 
         final long newLength = len + items.length;
-        sobj.set("length", newLength, true);
+        sobj.set("length", newLength, CALLSITE_STRICT);
 
         return newLength;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java	Mon Sep 22 13:28:28 2014 +0200
@@ -42,6 +42,7 @@
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.events.RuntimeEvent;
 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 
 /**
  * Nashorn specific debug utils. This is meant for Nashorn developers.
@@ -266,7 +267,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
-        ((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, true);
+        ((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, NashornCallSiteDescriptor.CALLSITE_STRICT);
     }
 
     /**
@@ -355,7 +356,7 @@
         if (sobj.has(EVENT_QUEUE)) {
             q = (LinkedList<RuntimeEvent<?>>)((ScriptObject)self).get(EVENT_QUEUE);
         } else {
-            ((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), true);
+            ((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), NashornCallSiteDescriptor.CALLSITE_STRICT);
         }
         return q;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Mon Sep 22 13:28:28 2014 +0200
@@ -250,146 +250,146 @@
     }
 
     @Override
-    public void set(final Object key, final int value, final boolean strict) {
+    public void set(final Object key, final int value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final Object key, final long value, final boolean strict) {
+    public void set(final Object key, final long value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final Object key, final double value, final boolean strict) {
+    public void set(final Object key, final double value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final Object key, final Object value, final boolean strict) {
+    public void set(final Object key, final Object value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final double key, final int value, final boolean strict) {
+    public void set(final double key, final int value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final double key, final long value, final boolean strict) {
+    public void set(final double key, final long value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final double key, final double value, final boolean strict) {
+    public void set(final double key, final double value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final double key, final Object value, final boolean strict) {
+    public void set(final double key, final Object value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final long key, final int value, final boolean strict) {
+    public void set(final long key, final int value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final long key, final long value, final boolean strict) {
+    public void set(final long key, final long value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final long key, final double value, final boolean strict) {
+    public void set(final long key, final double value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final long key, final Object value, final boolean strict) {
+    public void set(final long key, final Object value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final int key, final int value, final boolean strict) {
+    public void set(final int key, final int value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final int key, final long value, final boolean strict) {
+    public void set(final int key, final long value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final int key, final double value, final boolean strict) {
+    public void set(final int key, final double value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
     @Override
-    public void set(final int key, final Object value, final boolean strict) {
+    public void set(final int key, final Object value, final int flags) {
         if (overrides && super.hasOwnProperty(key)) {
-            super.set(key, value, strict);
+            super.set(key, value, flags);
         } else {
-            callAdaptee(__put__, key, value, strict);
+            callAdaptee(__put__, key, value, flags);
         }
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java	Mon Sep 22 13:28:28 2014 +0200
@@ -191,7 +191,7 @@
         state.gap = gap;
 
         final ScriptObject wrapper = Global.newEmptyInstance();
-        wrapper.set("", value, false);
+        wrapper.set("", value, 0);
 
         return str("", wrapper, state);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java	Mon Sep 22 13:28:28 2014 +0200
@@ -146,7 +146,7 @@
         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
         final Object value = createProperty(name);
         if(value != null) {
-            set(name, value, false);
+            set(name, value, 0);
             return true;
         }
         return false;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java	Mon Sep 22 13:28:28 2014 +0200
@@ -112,82 +112,82 @@
     }
 
     @Override
-    public void set(final double key, final int value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final double key, final int value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final double key, final long value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final double key, final long value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final double key, final double value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final double key, final double value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final double key, final Object value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final double key, final Object value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final long key, final int value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final long key, final int value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final long key, final long value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final long key, final long value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final long key, final double value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final long key, final double value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final long key, final Object value, final boolean strict) {
-        set(JSType.toObject(key), value, strict);
+    public void set(final long key, final Object value, final int flags) {
+        set(JSType.toObject(key), value, flags);
     }
 
     @Override
-    public void set(final int key, final int value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final int key, final int value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final int key, final long value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final int key, final long value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final int key, final double value, final boolean strict) {
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+    public void set(final int key, final double value, final int flags) {
+        set(JSType.toObject(key), JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final int key, final Object value, final boolean strict) {
-        set(JSType.toObject(key), value, strict);
+    public void set(final int key, final Object value, final int flags) {
+        set(JSType.toObject(key), value, flags);
     }
 
     @Override
-    public void set(final Object key, final int value, final boolean strict) {
-        set(key, JSType.toObject(value), strict);
+    public void set(final Object key, final int value, final int flags) {
+        set(key, JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final Object key, final long value, final boolean strict) {
-        set(key, JSType.toObject(value), strict);
+    public void set(final Object key, final long value, final int flags) {
+        set(key, JSType.toObject(value), flags);
     }
 
     @Override
-    public void set(final Object key, final double value, final boolean strict) {
-        set(key, JSType.toObject(value), strict);
+    public void set(final Object key, final double value, final int flags) {
+        set(key, JSType.toObject(value), flags);
     }
 
     @Override
-    public abstract void set(Object key, Object value, boolean strict);
+    public abstract void set(Object key, Object value, int flags);
 
     @Override
     public abstract boolean has(Object key);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ECMAException.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ECMAException.java	Mon Sep 22 13:28:28 2014 +0200
@@ -285,7 +285,7 @@
             if (!sobj.has(EXCEPTION_PROPERTY)) {
                 sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
             } else {
-                sobj.set(EXCEPTION_PROPERTY, this, false);
+                sobj.set(EXCEPTION_PROPERTY, this, 0);
             }
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java	Mon Sep 22 13:28:28 2014 +0200
@@ -139,6 +139,17 @@
     }
 
     /**
+     * Return the {@code ScriptObject} where the search started. This is usually the ScriptObject the
+     * operation was started on, except for properties found inside a 'with' statement, where it is the
+     * top-level 'with' expression object.
+     *
+     * @return the start object.
+     */
+    public ScriptObject getSelf() {
+        return self;
+    }
+
+    /**
      * Return the appropriate receiver for a getter.
      * @return appropriate receiver
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java	Mon Sep 22 13:28:28 2014 +0200
@@ -309,7 +309,7 @@
      *
      * @param find    property lookup
      * @param inv     normal guarded invocation for this setter, as computed by the ScriptObject linker
-     * @param desc    callsite descriptr
+     * @param desc    callsite descriptor
      * @param request link request
      *
      * @return null if failed to set up constant linkage
@@ -376,8 +376,12 @@
      * @return resulting getter, or null if failed to create constant
      */
     synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
-        // Also return null if property may have side effects
-        if ((GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) {
+        // Only use constant getter for fast scope access, because the receiver may change between invocations
+        // for slow-scope and non-scope callsites.
+        // Also return null for user accessor properties as they may have side effects.
+        if (!NashornCallSiteDescriptor.isFastScope(desc)
+                || (GLOBAL_ONLY && !find.getOwner().isGlobal())
+                || find.getProperty() instanceof UserAccessorProperty) {
             return null;
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java	Mon Sep 22 13:28:28 2014 +0200
@@ -122,7 +122,7 @@
                 if (newElement == ScriptRuntime.UNDEFINED) {
                     valueObj.delete(key, false);
                 } else {
-                    setPropertyValue(valueObj, key, newElement, false);
+                    setPropertyValue(valueObj, key, newElement);
                 }
             }
         }
@@ -179,7 +179,7 @@
 
                 final String name = pNode.getKeyName();
                 final Object value = convertNode(global, valueNode);
-                setPropertyValue(object, name, value, false);
+                setPropertyValue(object, name, value);
             }
 
             return object;
@@ -193,14 +193,14 @@
     }
 
     // add a new property if does not exist already, or else set old property
-    private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
+    private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value) {
         final int index = ArrayIndex.getArrayIndex(name);
         if (ArrayIndex.isValidArrayIndex(index)) {
             // array index key
             sobj.defineOwnProperty(index, value);
         } else if (sobj.getMap().findProperty(name) != null) {
             // pre-existing non-inherited property, call set
-            sobj.set(name, value, strict);
+            sobj.set(name, value, 0);
         } else {
             // add new property
             sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Mon Sep 22 13:28:28 2014 +0200
@@ -256,7 +256,7 @@
             final Object constructor = BeansLinker.getConstructorMethod(
                     javaClass, propertyName.substring(openBrace + 1, lastChar));
             if (constructor != null) {
-                set(propertyName, constructor, false);
+                set(propertyName, constructor, 0);
                 return constructor;
             }
             // we didn't find a matching constructor!
@@ -270,7 +270,7 @@
             propertyValue = StaticClass.forClass(javaClass);
         }
 
-        set(propertyName, propertyValue, false);
+        set(propertyName, propertyValue, 0);
         return propertyValue;
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyAccess.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyAccess.java	Mon Sep 22 13:28:28 2014 +0200
@@ -163,129 +163,129 @@
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(Object key, int value, boolean strict);
+    public void set(Object key, int value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(Object key, long value, boolean strict);
+    public void set(Object key, long value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(Object key, double value, boolean strict);
+    public void set(Object key, double value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(Object key, Object value, boolean strict);
+    public void set(Object key, Object value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(double key, int value, boolean strict);
+    public void set(double key, int value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(double key, long value, boolean strict);
+    public void set(double key, long value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(double key, double value, boolean strict);
+    public void set(double key, double value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(double key, Object value, boolean strict);
+    public void set(double key, Object value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(long key, int value, boolean strict);
+    public void set(long key, int value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(long key, long value, boolean strict);
+    public void set(long key, long value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(long key, double value, boolean strict);
+    public void set(long key, double value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(long key, Object value, boolean strict);
+    public void set(long key, Object value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(int key, int value, boolean strict);
+    public void set(int key, int value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(int key, long value, boolean strict);
+    public void set(int key, long value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(int key, double value, boolean strict);
+    public void set(int key, double value, int flags);
 
     /**
      * Set the value of a given key
      * @param key     the key
      * @param value   the value
-     * @param strict  are we in strict mode
+     * @param flags   call site flags
      */
-    public void set(int key, Object value, boolean strict);
+    public void set(int key, Object value, int flags);
 
     /**
      * Check if the given key exists anywhere in the proto chain
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java	Mon Sep 22 13:28:28 2014 +0200
@@ -45,6 +45,7 @@
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 
 /**
  * Used to signal to the linker to relink the callee
@@ -161,7 +162,7 @@
                 assert runtimeScope == null;
                 runtimeScope = (ScriptObject)value;
             } else if(name != null) {
-                locals.set(name, value, true);
+                locals.set(name, value, NashornCallSiteDescriptor.CALLSITE_STRICT);
             }
         }
         locals.setProto(runtimeScope);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Sep 22 13:28:28 2014 +0200
@@ -198,10 +198,10 @@
     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 
     static final MethodHandle[] SET_SLOW = new MethodHandle[] {
-        findOwnMH_V("set", void.class, Object.class, int.class, boolean.class),
-        findOwnMH_V("set", void.class, Object.class, long.class, boolean.class),
-        findOwnMH_V("set", void.class, Object.class, double.class, boolean.class),
-        findOwnMH_V("set", void.class, Object.class, Object.class, boolean.class)
+        findOwnMH_V("set", void.class, Object.class, int.class, int.class),
+        findOwnMH_V("set", void.class, Object.class, long.class, int.class),
+        findOwnMH_V("set", void.class, Object.class, double.class, int.class),
+        findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
     };
 
     /** Method handle to reset the map of this ScriptObject */
@@ -593,7 +593,7 @@
             if (newValue && property != null) {
                 // Temporarily clear flags.
                 property = modifyOwnProperty(property, 0);
-                set(key, value, false);
+                set(key, value, 0);
                 //this might change the map if we change types of the property
                 //hence we need to read it again. note that we should probably
                 //have the setter return the new property throughout and in
@@ -758,7 +758,7 @@
      * @return FindPropertyData or null if not found.
      */
     public final FindProperty findProperty(final String key, final boolean deep) {
-        return findProperty(key, deep, false, this);
+        return findProperty(key, deep, this);
     }
 
     /**
@@ -775,16 +775,11 @@
      *
      * @param key  Property key.
      * @param deep Whether the search should look up proto chain.
-     * @param stopOnNonScope should a deep search stop on the first non-scope object?
      * @param start the object on which the lookup was originally initiated
      *
      * @return FindPropertyData or null if not found.
      */
-    FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
-        // if doing deep search, stop search on the first non-scope object if asked to do so
-        if (stopOnNonScope && start != this && !isScope()) {
-            return null;
-        }
+    FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
 
         final PropertyMap selfMap  = getMap();
         final Property    property = selfMap.findProperty(key);
@@ -796,7 +791,7 @@
         if (deep) {
             final ScriptObject myProto = getProto();
             if (myProto != null) {
-                return myProto.findProperty(key, deep, stopOnNonScope, start);
+                return myProto.findProperty(key, deep, start);
             }
         }
 
@@ -1164,7 +1159,7 @@
      * @param value the value to write at the given index
      */
     public void setArgument(final int key, final Object value) {
-        set(key, value, false);
+        set(key, value, 0);
     }
 
     /**
@@ -1725,7 +1720,8 @@
      */
     public Object put(final Object key, final Object value, final boolean strict) {
         final Object oldValue = get(key);
-        set(key, value, strict);
+        final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+        set(key, value, flags);
         return oldValue;
     }
 
@@ -1738,8 +1734,9 @@
      * @param strict strict mode or not
      */
     public void putAll(final Map<?, ?> otherMap, final boolean strict) {
+        final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
         for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
-            set(entry.getKey(), entry.getValue(), strict);
+            set(entry.getKey(), entry.getValue(), flags);
         }
     }
 
@@ -2042,7 +2039,7 @@
 
         final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
         setMap(newMap);
-        set(key, value, true);
+        set(key, value, 0);
     }
 
     /**
@@ -2135,7 +2132,6 @@
             return findMegaMorphicSetMethod(desc, name);
         }
 
-        final boolean scope                   = isScope();
         final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
 
         /*
@@ -2145,16 +2141,18 @@
          *
          * toString = function() { print("global toString"); } // don't affect Object.prototype.toString
          */
-        FindProperty find = findProperty(name, true, scope, this);
+        FindProperty find = findProperty(name, true, this);
 
         // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
-        if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
+        if (find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
             // We should still check if inherited data property is not writable
             if (isExtensible() && !find.getProperty().isWritable()) {
-                return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", false);
+                return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
             }
-            // Otherwise, forget the found property
-            find = null;
+            // Otherwise, forget the found property unless this is a scope callsite and the owner is a scope object as well.
+            if (!NashornCallSiteDescriptor.isScope(desc) || !find.getOwner().isScope()) {
+                find = null;
+            }
         }
 
         if (find != null) {
@@ -2180,8 +2178,8 @@
 
     private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String strictErrorMessage, final boolean canBeFastScope) {
         final String  name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
-         if (NashornCallSiteDescriptor.isStrict(desc)) {
-           throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString(this));
+        if (NashornCallSiteDescriptor.isStrict(desc)) {
+            throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString(this));
         }
         assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
         return new GuardedInvocation(
@@ -2207,7 +2205,7 @@
     private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
         final MethodType        type = desc.getMethodType().insertParameterTypes(1, Object.class);
         //never bother with ClassCastExceptionGuard for megamorphic callsites
-        final GuardedInvocation inv = findSetIndexMethod(getClass(), false, type, NashornCallSiteDescriptor.isStrict(desc));
+        final GuardedInvocation inv = findSetIndexMethod(getClass(), desc, false, type);
         return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
     }
 
@@ -2230,24 +2228,26 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
-        return findSetIndexMethod(getClass(), explicitInstanceOfCheck(desc, request), desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
+        return findSetIndexMethod(getClass(), desc, explicitInstanceOfCheck(desc, request), desc.getMethodType());
     }
 
     /**
      * Find the appropriate SETINDEX method for an invoke dynamic call.
      *
+     * @param clazz the receiver class
+     * @param desc  the call site descriptor
+     * @param explicitInstanceOfCheck add an explicit instanceof check?
      * @param callType the method type at the call site
-     * @param isStrict are we in strict mode?
      *
      * @return GuardedInvocation to be invoked at call site.
      */
-    private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final boolean explicitInstanceOfCheck, final MethodType callType, final boolean isStrict) {
+    private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final MethodType callType) {
         assert callType.parameterCount() == 3;
         final Class<?> keyClass   = callType.parameterType(1);
         final Class<?> valueClass = callType.parameterType(2);
 
-        MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, boolean.class);
-        methodHandle = MH.insertArguments(methodHandle, 3, isStrict);
+        MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, int.class);
+        methodHandle = MH.insertArguments(methodHandle, 3, NashornCallSiteDescriptor.getFlags(desc));
 
         return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
     }
@@ -2672,7 +2672,7 @@
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
-                    final FindProperty find = object.findProperty(key, false, false, this);
+                    final FindProperty find = object.findProperty(key, false, this);
 
                     if (find != null) {
                         return getIntValue(find, programPoint);
@@ -2755,7 +2755,7 @@
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
-                    final FindProperty find = object.findProperty(key, false, false, this);
+                    final FindProperty find = object.findProperty(key, false, this);
                     if (find != null) {
                         return getLongValue(find, programPoint);
                     }
@@ -2837,7 +2837,7 @@
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
-                    final FindProperty find = object.findProperty(key, false, false, this);
+                    final FindProperty find = object.findProperty(key, false, this);
                     if (find != null) {
                         return getDoubleValue(find, programPoint);
                     }
@@ -2919,7 +2919,7 @@
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
-                    final FindProperty find = object.findProperty(key, false, false, this);
+                    final FindProperty find = object.findProperty(key, false, this);
 
                     if (find != null) {
                         return find.getObjectValue();
@@ -2996,48 +2996,48 @@
         return get(index, JSType.toString(key));
     }
 
-    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final boolean strict) {
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
         if (getMap().containsArrayKeys()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
-                setObject(find, strict, key, value);
+                setObject(find, callSiteFlags, key, value);
                 return true;
             }
         }
         return false;
     }
 
-    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final boolean strict) {
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final int callSiteFlags) {
         if (getMap().containsArrayKeys()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
-                setObject(find, strict, key, value);
+                setObject(find, callSiteFlags, key, value);
                 return true;
             }
         }
         return false;
     }
 
-    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final boolean strict) {
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
          if (getMap().containsArrayKeys()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
-                setObject(find, strict, key, value);
+                setObject(find, callSiteFlags, key, value);
                 return true;
             }
         }
         return false;
     }
 
-    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final boolean strict) {
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final int callSiteFlags) {
         if (getMap().containsArrayKeys()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
-                setObject(find, strict, key, value);
+                setObject(find, callSiteFlags, key, value);
                 return true;
             }
         }
@@ -3045,10 +3045,10 @@
     }
 
     //value agnostic
-    private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final boolean strict) {
+    private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
         if (longIndex >= oldLength) {
             if (!isExtensible()) {
-                if (strict) {
+                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
                 }
                 return true;
@@ -3068,37 +3068,41 @@
         }
     }
 
-    private void doesNotHave(final int index, final int value, final boolean strict) {
+    private void doesNotHave(final int index, final int value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
-        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
-    private void doesNotHave(final int index, final long value, final boolean strict) {
+    private void doesNotHave(final int index, final long value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
-        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
-    private void doesNotHave(final int index, final double value, final boolean strict) {
+    private void doesNotHave(final int index, final double value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
-        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
-    private void doesNotHave(final int index, final Object value, final boolean strict) {
+    private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
-        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
@@ -3108,32 +3112,47 @@
      * This is the most generic of all Object setters. Most of the others use this in some form.
      * TODO: should be further specialized
      *
-     * @param find    found property
-     * @param strict  are we in strict mode
-     * @param key     property key
-     * @param value   property value
+     * @param find          found property
+     * @param callSiteFlags callsite flags
+     * @param key           property key
+     * @param value         property value
      */
-    public final void setObject(final FindProperty find, final boolean strict, final String key, final Object value) {
+    public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) {
         FindProperty f = find;
 
-        if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty) && !isScope()) {
-            // Setting a property should not modify the property in prototype unless this is a scope object.
-            f = null;
+        if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
+            final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
+            // If the start object of the find is not this object it means the property was found inside a
+            // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
+            // to the 'with' object.
+            // Note that although a 'set' operation involving a with statement follows scope rules outside
+            // the 'with' expression (the 'set' operation is performed on the owning prototype if it exists),
+            // it follows non-scope rules inside the 'with' expression (set is performed on the top level object).
+            // This is why we clear the callsite flags and FindProperty in the forward call to the 'with' object.
+            if (isScope && f.getSelf() != this) {
+                f.getSelf().setObject(null, 0, key, value);
+                return;
+            }
+            // Setting a property should not modify the property in prototype unless this is a scope callsite
+            // and the owner is a scope object as well (with the exception of 'with' statement handled above).
+            if (!isScope || !f.getOwner().isScope()) {
+                f = null;
+            }
         }
 
         if (f != null) {
             if (!f.getProperty().isWritable()) {
-                if (strict) {
+                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
                     throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
                 }
 
                 return;
             }
 
-            f.setValue(value, strict);
+            f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
 
         } else if (!isExtensible()) {
-            if (strict) {
+            if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
                 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
             }
         } else {
@@ -3153,293 +3172,293 @@
     }
 
     @Override
-    public void set(final Object key, final int value, final boolean strict) {
+    public void set(final Object key, final int value, final int callSiteFlags) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(primitiveKey);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final Object key, final long value, final boolean strict) {
+    public void set(final Object key, final long value, final int callSiteFlags) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(primitiveKey);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final Object key, final double value, final boolean strict) {
+    public void set(final Object key, final double value, final int callSiteFlags) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(primitiveKey);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final Object key, final Object value, final boolean strict) {
+    public void set(final Object key, final Object value, final int callSiteFlags) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(primitiveKey);
-        setObject(findProperty(propName, true), strict, propName, value);
+        setObject(findProperty(propName, true), callSiteFlags, propName, value);
     }
 
     @Override
-    public void set(final double key, final int value, final boolean strict) {
+    public void set(final double key, final int value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final double key, final long value, final boolean strict) {
+    public void set(final double key, final long value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final double key, final double value, final boolean strict) {
+    public void set(final double key, final double value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final double key, final Object value, final boolean strict) {
+    public void set(final double key, final Object value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, value);
+        setObject(findProperty(propName, true), callSiteFlags, propName, value);
     }
 
     @Override
-    public void set(final long key, final int value, final boolean strict) {
+    public void set(final long key, final int value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final long key, final long value, final boolean strict) {
+    public void set(final long key, final long value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final long key, final double value, final boolean strict) {
+    public void set(final long key, final double value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final long key, final Object value, final boolean strict) {
+    public void set(final long key, final Object value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, value);
+        setObject(findProperty(propName, true), callSiteFlags, propName, value);
     }
 
     @Override
-    public void set(final int key, final int value, final boolean strict) {
+    public void set(final int key, final int value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final long value, final boolean strict) {
+    public void set(final int key, final long value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final double value, final boolean strict) {
+    public void set(final int key, final double value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+        setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final Object value, final boolean strict) {
+    public void set(final int key, final Object value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
+                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
             } else {
-                doesNotHave(index, value, strict);
+                doesNotHave(index, value, callSiteFlags);
             }
 
             return;
         }
 
         final String propName = JSType.toString(key);
-        setObject(findProperty(propName, true), strict, propName, value);
+        setObject(findProperty(propName, true), callSiteFlags, propName, value);
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Mon Sep 22 13:28:28 2014 +0200
@@ -221,9 +221,9 @@
         final String err = errBuffer.toString();
 
         // Set globals for secondary results.
-        global.set(OUT_NAME, out, false);
-        global.set(ERR_NAME, err, false);
-        global.set(EXIT_NAME, exit, false);
+        global.set(OUT_NAME, out, 0);
+        global.set(ERR_NAME, err, 0);
+        global.set(EXIT_NAME, exit, 0);
 
         // Propagate exception if present.
         for (final IOException element : exception) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java	Mon Sep 22 13:28:28 2014 +0200
@@ -205,7 +205,7 @@
 
         //slow setter, that calls ScriptObject.set with appropraite type and key name
         MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
-        slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.isStrict(desc));
+        slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
         slowSetter = MH.insertArguments(slowSetter, 1, name);
         slowSetter = MH.asType(slowSetter, slowSetter.type().changeParameterType(0, Object.class));
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java	Mon Sep 22 13:28:28 2014 +0200
@@ -34,6 +34,7 @@
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 
 /**
  * Unique instance of this class is used to represent JavaScript undefined.
@@ -128,7 +129,7 @@
     }
 
     private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
-    private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, boolean.class), 3, Boolean.TRUE);
+    private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, int.class), 3, NashornCallSiteDescriptor.CALLSITE_STRICT);
 
     private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
         return new GuardedInvocation(MH.insertArguments(GET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
@@ -152,7 +153,7 @@
     }
 
     @Override
-    public void set(final Object key, final Object value, final boolean strict) {
+    public void set(final Object key, final Object value, final int flags) {
         throw typeError("cant.set.property.of.undefined", ScriptRuntime.safeToString(key));
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java	Mon Sep 22 13:28:28 2014 +0200
@@ -193,18 +193,20 @@
      *
      * @param key  Property key.
      * @param deep Whether the search should look up proto chain.
-     * @param stopOnNonScope should a deep search stop on the first non-scope object?
      * @param start the object on which the lookup was originally initiated
      *
      * @return FindPropertyData or null if not found.
      */
     @Override
-    FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
-        final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start);
+    FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
+        // We call findProperty on 'expression' with 'expression' itself as start parameter.
+        // This way in ScriptObject.setObject we can tell the property is from a 'with' expression
+        // (as opposed from another non-scope object in the proto chain such as Object.prototype).
+        final FindProperty exprProperty = expression.findProperty(key, true, expression);
         if (exprProperty != null) {
              return exprProperty;
         }
-        return super.findProperty(key, deep, stopOnNonScope, start);
+        return super.findProperty(key, deep, start);
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Fri Sep 19 13:13:20 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Mon Sep 22 13:28:28 2014 +0200
@@ -255,7 +255,7 @@
      * @return the Nashorn-specific flags for the call site, or 0 if the passed descriptor is not a Nashorn call site
      * descriptor.
      */
-    private static int getFlags(final CallSiteDescriptor desc) {
+    public static int getFlags(final CallSiteDescriptor desc) {
         return desc instanceof NashornCallSiteDescriptor ? ((NashornCallSiteDescriptor)desc).flags : 0;
     }
 
@@ -343,6 +343,24 @@
     }
 
     /**
+     * Returns true if {@code flags} has the {@link  #CALLSITE_STRICT} bit set.
+     * @param flags the flags
+     * @return true if the flag is set, false otherwise.
+     */
+    public static boolean isStrictFlag(final int flags) {
+        return (flags & CALLSITE_STRICT) != 0;
+    }
+
+    /**
+     * Returns true if {@code flags} has the {@link  #CALLSITE_SCOPE} bit set.
+     * @param flags the flags
+     * @return true if the flag is set, false otherwise.
+     */
+    public static boolean isScopeFlag(final int flags) {
+        return (flags & CALLSITE_SCOPE) != 0;
+    }
+
+    /**
      * Get a program point from a descriptor (must be optimistic)
      * @param desc descriptor
      * @return program point
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8047764-strict.js	Mon Sep 22 13:28:28 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8047764: Indexed or polymorphic set on global affects Object.prototype
+ *
+ * @test
+ * @run
+ */
+
+// Same as JDK-8047764.js but running in strict mode
+"use strict";
+
+// Test global set operation on properties defined in Object.prototype
+
+Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
+Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
+
+try {
+    prop1 = 1;
+    print("prop 1: " + prop2);
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    prop2 = 2;
+    print("prop 2: " + prop2);
+} catch (e) {
+    print(e.name);
+}
+
+// Make sure various ways of setting global toString don't affect Object.prototype.toString
+
+function checkToString() {
+    print(global);
+    print(Object.prototype);
+    print(global.toString === Object.prototype.toString);
+    print(objProtoToString === Object.prototype.toString);
+}
+
+var global = this;
+var objProtoToString = Object.prototype.toString;
+global["toString"] = function() { return "global toString 1"; };
+checkToString();
+global.toString = function() { return "global toString 2"; };
+checkToString();
+toString = function() { return "global toString 3"; };
+checkToString();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8047764-strict.js.EXPECTED	Mon Sep 22 13:28:28 2014 +0200
@@ -0,0 +1,15 @@
+setting prop1: 1
+prop 1: 1
+TypeError
+global toString 1
+[object Object]
+false
+true
+global toString 2
+[object Object]
+false
+true
+global toString 3
+[object Object]
+false
+true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8047764.js	Mon Sep 22 13:28:28 2014 +0200
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8047764: Indexed or polymorphic set on global affects Object.prototype
+ *
+ * @test
+ * @run
+ */
+
+// Test global set operation on properties defined in Object.prototype
+
+Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
+Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
+
+try {
+    prop1 = 1;
+    print("prop 1: " + prop2);
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    prop2 = 2;
+    print("prop 2: " + prop2);
+} catch (e) {
+    print(e.name);
+}
+
+// Make sure various ways of setting global toString don't affect Object.prototype.toString
+
+function checkToString() {
+    print(global);
+    print(Object.prototype);
+    print(global.toString === Object.prototype.toString);
+    print(objProtoToString === Object.prototype.toString);
+}
+
+var global = this;
+var objProtoToString = Object.prototype.toString;
+global["toString"] = function() { return "global toString 1"; };
+checkToString();
+global.toString = function() { return "global toString 2"; };
+checkToString();
+toString = function() { return "global toString 3"; };
+checkToString();
+
+// Test setters on 'with' object
+
+var p = { prop3: 3, toString: function() { return "[object p]"; }};
+Object.defineProperty(p, "prop4", { get: function() { print("get", this); return 4; }, set: function(v) { print("set", this, v); }});
+var o = Object.create(p);
+o.toString = function() { return "[object o]"; };
+
+with(o) {
+    (function() {
+        var m = 5;
+        (function() {
+            print(prop3);
+            prop3 = m;
+            print(prop3);
+            print(prop4);
+            prop4 = m;
+            print(prop4);
+        })();
+    })();
+}
+
+print(o.hasOwnProperty("prop3"));
+print(o.prop3);
+print(p.prop3);
+print(o.hasOwnProperty("prop4"));
+print(o.prop4);
+print(p.prop4);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8047764.js.EXPECTED	Mon Sep 22 13:28:28 2014 +0200
@@ -0,0 +1,30 @@
+setting prop1: 1
+prop 1: 1
+prop 2: 1
+global toString 1
+[object Object]
+false
+true
+global toString 2
+[object Object]
+false
+true
+global toString 3
+[object Object]
+false
+true
+3
+5
+get [object o]
+4
+set [object o] 5
+get [object o]
+4
+true
+5
+3
+false
+get [object o]
+4
+get [object p]
+4