# HG changeset patch # User sundar # Date 1378737641 -19800 # Node ID c3b6ce7b74bff5886bb22098bfd4d4e74d6ef0df # Parent 7ae16963948553dfcd6756bfe2029d10f84d7797 8024180: Incorrect handling of expression and parent scope in 'with' statements Reviewed-by: jlaskey, hannesw diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Sep 09 20:10:41 2013 +0530 @@ -315,7 +315,7 @@ final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz; realSelf = mirror.getScriptObject(); realGlobal = mirror.getHomeGlobal(); - if (! realGlobal.isOfContext(nashornContext)) { + if (! isOfContext(realGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } else if (thiz instanceof ScriptObject) { @@ -326,7 +326,7 @@ throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); } - if (! realGlobal.isOfContext(nashornContext)) { + if (! isOfContext(realGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } @@ -394,7 +394,7 @@ // Retrieve nashorn Global object from a given ScriptObjectMirror private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) { ScriptObject sobj = mirror.getScriptObject(); - if (sobj instanceof GlobalObject && sobj.isOfContext(nashornContext)) { + if (sobj instanceof GlobalObject && isOfContext(sobj, nashornContext)) { return sobj; } @@ -470,7 +470,7 @@ ScriptObjectMirror selfMirror = null; if (selfObject instanceof ScriptObjectMirror) { selfMirror = (ScriptObjectMirror)selfObject; - if (! selfMirror.getHomeGlobal().isOfContext(nashornContext)) { + if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } else if (selfObject instanceof ScriptObject) { @@ -481,7 +481,7 @@ throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); } - if (! oldGlobal.isOfContext(nashornContext)) { + if (! isOfContext(oldGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } @@ -617,4 +617,9 @@ } return true; } + + private static boolean isOfContext(final ScriptObject global, final Context context) { + assert global instanceof GlobalObject: "Not a Global object"; + return ((GlobalObject)global).isOfContext(context); + } } diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/api/scripting/ScriptObjectMirror.java --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Mon Sep 09 20:10:41 2013 +0530 @@ -42,6 +42,7 @@ import java.util.concurrent.Callable; import javax.script.Bindings; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -62,6 +63,7 @@ private final ScriptObject sobj; private final ScriptObject global; + private final boolean strict; @Override public boolean equals(final Object other) { @@ -101,7 +103,7 @@ final Object val = functionName == null? sobj : sobj.get(functionName); if (val instanceof ScriptFunction) { final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); + return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { return ((ScriptObjectMirror)val).call(null, args); } @@ -131,7 +133,7 @@ final Object val = functionName == null? sobj : sobj.get(functionName); if (val instanceof ScriptFunction) { final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global); + return wrap(ScriptRuntime.construct((ScriptFunction)val, unwrapArray(modArgs, global)), global); } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { return ((ScriptObjectMirror)val).newObject(null, args); } @@ -197,7 +199,7 @@ public void setSlot(final int index, final Object value) { inGlobal(new Callable() { @Override public Void call() { - sobj.set(index, unwrap(value, global), global.isStrictContext()); + sobj.set(index, unwrap(value, global), strict); return null; } }); @@ -209,7 +211,7 @@ public void clear() { inGlobal(new Callable() { @Override public Object call() { - sobj.clear(); + sobj.clear(strict); return null; } }); @@ -292,7 +294,7 @@ return inGlobal(new Callable() { @Override public Object call() { final Object modValue = globalChanged? wrap(value, oldGlobal) : value; - return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global)), global)); + return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global)); } }); } @@ -303,7 +305,6 @@ final boolean globalChanged = (oldGlobal != global); inGlobal(new Callable() { @Override public Object call() { - final boolean strict = global.isStrictContext(); for (final Map.Entry entry : map.entrySet()) { final Object value = entry.getValue(); final Object modValue = globalChanged? wrap(value, oldGlobal) : value; @@ -318,7 +319,7 @@ public Object remove(final Object key) { return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.remove(unwrap(key, global)), global); + return wrap(sobj.remove(unwrap(key, global), strict), global); } }); } @@ -333,7 +334,7 @@ public boolean delete(final Object key) { return inGlobal(new Callable() { @Override public Boolean call() { - return sobj.delete(unwrap(key, global)); + return sobj.delete(unwrap(key, global), strict); } }); } @@ -637,10 +638,11 @@ ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) { assert sobj != null : "ScriptObjectMirror on null!"; - assert global != null : "null global for ScriptObjectMirror!"; + assert global instanceof GlobalObject : "global is not a GlobalObject"; this.sobj = sobj; this.global = global; + this.strict = ((GlobalObject)global).isStrictContext(); } // accessors for script engine diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/objects/Global.java Mon Sep 09 20:10:41 2013 +0530 @@ -412,6 +412,14 @@ // initialized by nasgen private static PropertyMap $nasgenmap$; + // context to which this global belongs to + private final Context context; + + @Override + protected Context getContext() { + return context; + } + // performs initialization checks for Global constructor and returns the // PropertyMap, if everything is fine. private static PropertyMap checkAndGetMap(final Context context) { @@ -439,7 +447,7 @@ */ public Global(final Context context) { super(checkAndGetMap(context)); - this.setContext(context); + this.context = context; this.setIsScope(); final int cacheSize = context.getEnv()._class_cache_size; @@ -482,6 +490,16 @@ // GlobalObject interface implementation @Override + public boolean isOfContext(final Context context) { + return this.context == context; + } + + @Override + public boolean isStrictContext() { + return context.getEnv()._strict; + } + + @Override public void initBuiltinObjects() { if (this.builtinObject != null) { // already initialized, just return @@ -1765,7 +1783,7 @@ // do not fill $ENV if we have a security manager around // Retrieve current state of ENV variables. final ScriptObject env = newObject(); - env.putAll(System.getenv()); + env.putAll(System.getenv(), scriptEnv._strict); addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); } else { addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/Context.java --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/Context.java Mon Sep 09 20:10:41 2013 +0530 @@ -573,7 +573,7 @@ setGlobalTrusted(newGlobal); final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal); - newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped)); + newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped), env._strict); try { // wrap objects from newGlobal's world as mirrors - but if result diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/GlobalObject.java --- a/src/jdk/nashorn/internal/runtime/GlobalObject.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/GlobalObject.java Mon Sep 09 20:10:41 2013 +0530 @@ -37,6 +37,18 @@ public interface GlobalObject { /** + * Is this global of the given Context? + * @return true if this global belongs to the given Context + */ + public boolean isOfContext(Context context); + + /** + * Does this global belong to a strict Context? + * @return true if this global belongs to a strict Context + */ + public boolean isStrictContext(); + + /** * Initialize standard builtin objects like "Object", "Array", "Function" etc. * as well as our extension builtin objects like "Java", "JSAdapter" as properties * of the global scope object. diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/NativeJavaPackage.java --- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Mon Sep 09 20:10:41 2013 +0530 @@ -198,7 +198,7 @@ final String propertyName = desc.getNameToken(2); final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName; - final Context context = getContext(); + final Context context = Context.getContextTrusted(); Class javaClass = null; try { diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Mon Sep 09 20:10:41 2013 +0530 @@ -120,9 +120,6 @@ /** objects proto. */ private ScriptObject proto; - /** Context of the object, lazily cached. */ - private Context context; - /** Object flags. */ private int flags; @@ -1043,40 +1040,11 @@ } /** - * Return true if the script object context is strict - * @return true if strict context - */ - public final boolean isStrictContext() { - return getContext()._strict; - } - - /** - * Checks if this object belongs to the given context - * @param ctx context to check against - * @return true if this object belongs to the given context - */ - public final boolean isOfContext(final Context ctx) { - return context == ctx; - } - - /** * Return the current context from the object's map. * @return Current context. */ - protected final Context getContext() { - if (context == null) { - context = Context.fromClass(getClass()); - } - return context; - } - - /** - * Set the current context. - * @param ctx context instance to set - */ - protected final void setContext(final Context ctx) { - ctx.getClass(); - this.context = ctx; + protected Context getContext() { + return Context.fromClass(getClass()); } /** @@ -1482,9 +1450,10 @@ /** * Clears the properties from a ScriptObject * (java.util.Map-like method to help ScriptObjectMirror implementation) + * + * @param strict strict mode or not */ - public void clear() { - final boolean strict = isStrictContext(); + public void clear(final boolean strict) { final Iterator iter = propertyIterator(); while (iter.hasNext()) { delete(iter.next(), strict); @@ -1568,11 +1537,12 @@ * * @param key property key * @param value property value + * @param strict strict mode or not * @return oldValue if property with same key existed already */ - public Object put(final Object key, final Object value) { + public Object put(final Object key, final Object value, final boolean strict) { final Object oldValue = get(key); - set(key, value, isStrictContext()); + set(key, value, strict); return oldValue; } @@ -1582,9 +1552,9 @@ * (java.util.Map-like method to help ScriptObjectMirror implementation) * * @param otherMap a {@literal } map of properties to add + * @param strict strict mode or not */ - public void putAll(final Map otherMap) { - final boolean strict = isStrictContext(); + public void putAll(final Map otherMap, final boolean strict) { for (final Map.Entry entry : otherMap.entrySet()) { set(entry.getKey(), entry.getValue(), strict); } @@ -1595,26 +1565,16 @@ * (java.util.Map-like method to help ScriptObjectMirror implementation) * * @param key the key of the property + * @param strict strict mode or not * @return the oldValue of the removed property */ - public Object remove(final Object key) { + public Object remove(final Object key, final boolean strict) { final Object oldValue = get(key); - delete(key, isStrictContext()); + delete(key, strict); return oldValue; } /** - * Delete a property from the ScriptObject. - * (to help ScriptObjectMirror implementation) - * - * @param key the key of the property - * @return if the delete was successful or not - */ - public boolean delete(final Object key) { - return delete(key, isStrictContext()); - } - - /** * Return the size of the ScriptObject - i.e. the number of properties * it contains * (java.util.Map-like method to help ScriptObjectMirror implementation) @@ -2333,11 +2293,9 @@ return; } - final boolean isStrict = isStrictContext(); - if (newLength > arrayLength) { setArray(getArray().ensure(newLength - 1)); - if (getArray().canDelete(arrayLength, (newLength - 1), isStrict)) { + if (getArray().canDelete(arrayLength, (newLength - 1), false)) { setArray(getArray().delete(arrayLength, (newLength - 1))); } return; diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Mon Sep 09 20:10:41 2013 +0530 @@ -352,35 +352,6 @@ } /** - * Check that the target function is associated with current Context. And also make sure that 'self', if - * ScriptObject, is from current context. - * - * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve - * better performance by {@link Bootstrap#createDynamicInvoker(String, Class, Class...) creating a dynamic invoker} - * for operation {@code "dyn:call"}, then using its {@link MethodHandle#invokeExact(Object...)} method instead. - * - * @param target ScriptFunction object. - * @param self Receiver in call. - * @param args Call arguments. - * @return Call result. - */ - public static Object checkAndApply(final ScriptFunction target, final Object self, final Object... args) { - final ScriptObject global = Context.getGlobalTrusted(); - assert (global instanceof GlobalObject): "No current global set"; - - if (target.getContext() != global.getContext()) { - throw new IllegalArgumentException("'target' function is not from current Context"); - } - - if (self instanceof ScriptObject && ((ScriptObject)self).getContext() != global.getContext()) { - throw new IllegalArgumentException("'self' object is not from current Context"); - } - - // all in order - call real 'apply' - return apply(target, self, args); - } - - /** * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve * better performance by {@link Bootstrap#createDynamicInvoker(String, Class, Class...) creating a dynamic invoker} * for operation {@code "dyn:call"}, then using its {@link MethodHandle#invokeExact(Object...)} method instead. @@ -401,28 +372,6 @@ } /** - * Check that the target function is associated with current Context. - * And also make sure that 'self', if ScriptObject, is from current context. - * - * Call a function as a constructor given args. - * - * @param target ScriptFunction object. - * @param args Call arguments. - * @return Constructor call result. - */ - public static Object checkAndConstruct(final ScriptFunction target, final Object... args) { - final ScriptObject global = Context.getGlobalTrusted(); - assert (global instanceof GlobalObject): "No current global set"; - - if (target.getContext() != global.getContext()) { - throw new IllegalArgumentException("'target' function is not from current Context"); - } - - // all in order - call real 'construct' - return construct(target, args); - } - - /** * Call a script function as a constructor with given args. * * @param target ScriptFunction object. @@ -520,9 +469,12 @@ throw typeError(global, "cant.apply.with.to.null"); } - final ScriptObject withObject = new WithObject(scope, JSType.toScriptObject(global, expression)); + final Object wrappedExpr = JSType.toScriptObject(global, expression); + if (wrappedExpr instanceof ScriptObject) { + return new WithObject(scope, (ScriptObject)wrappedExpr); + } - return withObject; + throw typeError(global, "cant.apply.with.to.non.scriptobject"); } /** @@ -534,7 +486,7 @@ */ public static ScriptObject closeWith(final ScriptObject scope) { if (scope instanceof WithObject) { - return scope.getProto(); + return ((WithObject)scope).getParentScope(); } return scope; } diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/WithObject.java --- a/src/jdk/nashorn/internal/runtime/WithObject.java Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Mon Sep 09 20:10:41 2013 +0530 @@ -30,26 +30,26 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; - /** * This class supports the handling of scope in a with body. * */ public final class WithObject extends ScriptObject implements Scope { - + private static final MethodHandle WITHEXPRESSIONGUARD = findOwnMH("withExpressionGuard", boolean.class, Object.class, PropertyMap.class, SwitchPoint.class); private static final MethodHandle WITHEXPRESSIONFILTER = findOwnMH("withFilterExpression", Object.class, Object.class); private static final MethodHandle WITHSCOPEFILTER = findOwnMH("withFilterScope", Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression", Object.class, Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_FN = findOwnMH("bindToExpression", Object.class, ScriptFunction.class, Object.class); /** With expression object. */ - private final Object expression; + private final ScriptObject expression; /** * Constructor @@ -57,12 +57,13 @@ * @param scope scope object * @param expression with expression */ - WithObject(final ScriptObject scope, final Object expression) { + WithObject(final ScriptObject scope, final ScriptObject expression) { super(scope, null); setIsScope(); this.expression = expression; } + /** * Delete a property based on a key. * @param key Any valid JavaScript value. @@ -71,15 +72,13 @@ */ @Override public boolean delete(final Object key, final boolean strict) { - if (expression instanceof ScriptObject) { - final ScriptObject self = (ScriptObject)expression; - final String propName = JSType.toString(key); + final ScriptObject self = expression; + final String propName = JSType.toString(key); - final FindProperty find = self.findProperty(propName, true); + final FindProperty find = self.findProperty(propName, true); - if (find != null) { - return self.delete(propName, strict); - } + if (find != null) { + return self.delete(propName, strict); } return false; @@ -105,18 +104,16 @@ name = null; } - if (expression instanceof ScriptObject) { - self = (ScriptObject)expression; - if (isNamedOperation) { - find = self.findProperty(name, true); - } + self = expression; + if (isNamedOperation) { + find = self.findProperty(name, true); + } - if (find != null) { - link = self.lookup(desc, request); + if (find != null) { + link = self.lookup(desc, request); - if (link != null) { - return fixExpressionCallSite(ndesc, link); - } + if (link != null) { + return fixExpressionCallSite(ndesc, link); } } @@ -126,7 +123,7 @@ } if (find != null) { - return fixScopeCallSite(scope.lookup(desc, request)); + return fixScopeCallSite(scope.lookup(desc, request), name); } // the property is not found - now check for @@ -178,7 +175,7 @@ link = scope.lookup(desc, request); if (link != null) { - return fixScopeCallSite(link); + return fixScopeCallSite(link, name); } return null; @@ -197,11 +194,9 @@ */ @Override FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { - if (expression instanceof ScriptObject) { - final FindProperty exprProperty = ((ScriptObject)expression).findProperty(key, deep, stopOnNonScope, start); - if(exprProperty != null) { - return exprProperty; - } + final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start); + if (exprProperty != null) { + return exprProperty; } return super.findProperty(key, deep, stopOnNonScope, start); } @@ -220,16 +215,17 @@ * Get first parent scope that is not an instance of WithObject. */ private Scope getNonWithParent() { - ScriptObject proto = getProto(); + ScriptObject proto = getParentScope(); while (proto != null && proto instanceof WithObject) { - proto = proto.getProto(); + proto = ((WithObject)proto).getParentScope(); } assert proto instanceof Scope : "with scope without parent scope"; return (Scope) proto; } + private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { // The receiver may be an Object or a ScriptObject. final MethodType invType = link.getInvocation().type(); @@ -256,9 +252,13 @@ filterGuard(link, WITHEXPRESSIONFILTER)); } - private static GuardedInvocation fixScopeCallSite(final GuardedInvocation link) { + private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) { final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); - return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), filterGuard(newLink, WITHSCOPEFILTER)); + return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), + MH.guardWithTest( + expressionGuard(name), + filterGuard(newLink, WITHSCOPEFILTER), + MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class))); } private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) { @@ -279,7 +279,6 @@ return ((WithObject)receiver).expression; } - @SuppressWarnings("unused") private static Object bindToExpression(final Object fn, final Object receiver) { return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn; @@ -289,6 +288,17 @@ return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]); } + private MethodHandle expressionGuard(final String name) { + final PropertyMap map = expression.getMap(); + final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name); + return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp); + } + + @SuppressWarnings("unused") + private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) { + return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated()); + } + /** * Drops the WithObject wrapper from the scope. * @param receiver WithObject wrapper. @@ -302,10 +312,14 @@ * Get the with expression for this {@code WithObject} * @return the with expression */ - public Object getExpression() { + public ScriptObject getExpression() { return expression; } + public ScriptObject getParentScope() { + return getProto(); + } + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); } diff -r 7ae169639485 -r c3b6ce7b74bf src/jdk/nashorn/internal/runtime/resources/Messages.properties --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 05 21:17:06 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Sep 09 20:10:41 2013 +0530 @@ -110,6 +110,7 @@ type.error.cannot.get.default.number=Cannot get default number value type.error.cant.apply.with.to.null=Cannot apply "with" to null type.error.cant.apply.with.to.undefined=Cannot apply "with" to undefined +type.error.cant.apply.with.to.non.scriptobject=Cannot apply "with" to non script object type.error.in.with.non.object=Right hand side of "in" cannot be non-Object, found {0} type.error.prototype.not.an.object="prototype" of {0} is not an Object, it is {1} type.error.cant.load.script=Cannot load script from {0} diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/global_var_delete.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/global_var_delete.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,50 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + + +this.x = 44; + +function func() { + with({ }) { + print(x); + } +} + +func(); + +// delete global 'x' +delete this.x; + +try { + func(); +} catch(e) { + // expect ReferenceError + print(e); +} diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/global_var_delete.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/global_var_delete.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,2 @@ +44 +ReferenceError: "x" is not defined diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/global_var_shadow.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/global_var_shadow.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,45 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// global variable is shadowed by with 'expression' property +var user = { name: 'foo' }; + +function func(locals) { + with (locals) { + print(user.name); + } +} + +// global user.name 'foo' printed +func({}); + +// local user.name 'toto' printed +func({ user: { name: 'toto' } }); + diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/global_var_shadow.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/global_var_shadow.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,2 @@ +foo +toto diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/scope_no_such_prop.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/scope_no_such_prop.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,51 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// __noSuchProperty__ defined here confuses 'with' +// results in ReferenceError even when 'with' expression has +// the property + +load("nashorn:mozilla_compat.js") + +function func(locals) { + with (locals) { + print(user.name); + } +} + +try { + func({}); +} catch (e) { + print(e); +} + +// 'toto' expected in the call below +func({ user: { name: 'toto' } }); + diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/scope_no_such_prop.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/scope_no_such_prop.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,2 @@ +ReferenceError: user is not defined +toto diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_expr_prop_add.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_expr_prop_add.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,47 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +var obj = {}; +var x = "global x"; + +// adding property to 'with' xpression object should reflect +// as variable inside the 'with' block. +function func() { + with(obj) { + for (i = 0; i < 2; i++) { + print(x); + if (i == 0) { + obj.x = "obj.x"; + } + } + } +} + +func(); diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_expr_prop_add.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_expr_prop_add.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,2 @@ +global x +obj.x diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_expr_proto_prop_add.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_expr_proto_prop_add.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,49 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +var p = { }; +var obj = Object.create(p); + +var x = "global x"; + +// adding property to __proto__ of 'with' expression should +// reflect as a variable immediately. +function func() { + with(obj) { + for (i = 0; i < 2; i++) { + print(x); + if (i == 0) { + p.x = "p.x"; + } + } + } +} + +func(); diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_expr_proto_prop_add.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_expr_proto_prop_add.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,2 @@ +global x +p.x diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_java_object.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_java_object.js Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,36 @@ +/* + * 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-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// TypeError for with expression being non script object +try { + with(new java.lang.Object()) {} +} catch (e) { + print(e); +} diff -r 7ae169639485 -r c3b6ce7b74bf test/script/basic/8024180/with_java_object.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/8024180/with_java_object.js.EXPECTED Mon Sep 09 20:10:41 2013 +0530 @@ -0,0 +1,1 @@ +TypeError: Cannot apply "with" to non script object diff -r 7ae169639485 -r c3b6ce7b74bf test/src/jdk/nashorn/internal/runtime/ContextTest.java --- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java Thu Sep 05 21:17:06 2013 +0530 +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java Mon Sep 09 20:10:41 2013 +0530 @@ -64,6 +64,7 @@ final Options options = new Options(""); final ErrorManager errors = new ErrorManager(); final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader()); + final boolean strict = cx.getEnv()._strict; final ScriptObject oldGlobal = Context.getGlobal(); Context.setGlobal(cx.createGlobal()); @@ -95,7 +96,7 @@ assertEquals(sobj.size(), 2); // add property - sobj.put("zee", "hello"); + sobj.put("zee", "hello", strict); assertEquals(sobj.get("zee"), "hello"); assertEquals(sobj.size(), 3);