--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Jul 28 16:08:18 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Jul 28 16:44:11 2016 +0000
@@ -3057,6 +3057,7 @@
LexicalScope(final Global global) {
super(global, PropertyMap.newMap());
+ setIsInternal();
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jul 28 16:08:18 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jul 28 16:44:11 2016 +0000
@@ -123,6 +123,9 @@
/** Is this a builtin object? */
public static final int IS_BUILTIN = 1 << 3;
+ /** Is this an internal object that should not be visible to scripts? */
+ public static final int IS_INTERNAL = 1 << 4;
+
/**
* Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
* {@link ScriptObject#objectSpill} when full
@@ -1668,6 +1671,21 @@
}
/**
+ * Tag this script object as internal object that should not be visible to script code.
+ */
+ public final void setIsInternal() {
+ flags |= IS_INTERNAL;
+ }
+
+ /**
+ * Check if this script object is an internal object that should not be visible to script code.
+ * @return true if internal
+ */
+ public final boolean isInternal() {
+ return (flags & IS_INTERNAL) != 0;
+ }
+
+ /**
* Clears the properties from a ScriptObject
* (java.util.Map-like method to help ScriptObjectMirror implementation)
*
@@ -2045,7 +2063,13 @@
private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
final FindProperty find = findProperty(key, true, isScope, this);
if (find != null) {
- return find.getObjectValue();
+ // If this is a method invocation, and found property has a different self object then this,
+ // then return a function bound to the self object. This is the case for functions in with expressions.
+ final Object value = find.getObjectValue();
+ if (isMethod && value instanceof ScriptFunction && find.getSelf() != this && !find.getSelf().isInternal()) {
+ return ((ScriptFunction) value).createBound(find.getSelf(), ScriptRuntime.EMPTY_ARRAY);
+ }
+ return value;
}
return isMethod ? getNoSuchMethod(key, isScope, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, isScope, INVALID_PROGRAM_POINT);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Thu Jul 28 16:08:18 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Thu Jul 28 16:44:11 2016 +0000
@@ -66,6 +66,7 @@
WithObject(final ScriptObject scope, final ScriptObject expression) {
super(scope, null);
this.expression = expression;
+ setIsInternal();
}
/**
@@ -99,37 +100,23 @@
// With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of
// necessity have a Nashorn descriptor - it is safe to cast.
final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
- FindProperty find = null;
GuardedInvocation link = null;
- ScriptObject self;
-
- final boolean isNamedOperation;
- final String name;
final Operation op = desc.getOperation();
- if (op instanceof NamedOperation) {
- isNamedOperation = true;
- name = ((NamedOperation)op).getName().toString();
- } else {
- isNamedOperation = false;
- name = null;
- }
- self = expression;
- if (isNamedOperation) {
- find = self.findProperty(name, true);
- }
+ assert op instanceof NamedOperation; // WithObject is a scope object, access is always named
+ final String name = ((NamedOperation)op).getName().toString();
+
+ FindProperty find = expression.findProperty(name, true);
if (find != null) {
- link = self.lookup(desc, request);
+ link = expression.lookup(desc, request);
if (link != null) {
return fixExpressionCallSite(ndesc, link);
}
}
final ScriptObject scope = getProto();
- if (isNamedOperation) {
- find = scope.findProperty(name, true);
- }
+ find = scope.findProperty(name, true);
if (find != null) {
return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner());
@@ -137,43 +124,41 @@
// the property is not found - now check for
// __noSuchProperty__ and __noSuchMethod__ in expression
- if (self != null) {
- final String fallBack;
+ final String fallBack;
- final StandardOperation firstOp = ndesc.getFirstOperation();
- switch (firstOp) {
- case GET_METHOD:
- fallBack = NO_SUCH_METHOD_NAME;
- break;
- case GET_PROPERTY:
- case GET_ELEMENT:
- fallBack = NO_SUCH_PROPERTY_NAME;
- break;
- default:
- fallBack = null;
- break;
- }
+ final StandardOperation firstOp = ndesc.getFirstOperation();
+ switch (firstOp) {
+ case GET_METHOD:
+ fallBack = NO_SUCH_METHOD_NAME;
+ break;
+ case GET_PROPERTY:
+ case GET_ELEMENT:
+ fallBack = NO_SUCH_PROPERTY_NAME;
+ break;
+ default:
+ fallBack = null;
+ break;
+ }
- if (fallBack != null) {
- find = self.findProperty(fallBack, true);
- if (find != null) {
- switch (firstOp) {
- case GET_METHOD:
- link = self.noSuchMethod(desc, request);
- break;
- case GET_PROPERTY:
- case GET_ELEMENT:
- link = self.noSuchProperty(desc, request);
- break;
- default:
- break;
- }
+ if (fallBack != null) {
+ find = expression.findProperty(fallBack, true);
+ if (find != null) {
+ switch (firstOp) {
+ case GET_METHOD:
+ link = expression.noSuchMethod(desc, request);
+ break;
+ case GET_PROPERTY:
+ case GET_ELEMENT:
+ link = expression.noSuchProperty(desc, request);
+ break;
+ default:
+ break;
}
}
+ }
- if (link != null) {
- return fixExpressionCallSite(ndesc, link);
- }
+ if (link != null) {
+ return fixExpressionCallSite(ndesc, link);
}
// still not found, may be scope can handle with it's own
@@ -204,7 +189,7 @@
// (as opposed from another non-scope object in the proto chain such as Object.prototype).
final FindProperty exprProperty = expression.findProperty(key, true, false, expression);
if (exprProperty != null) {
- return exprProperty;
+ return exprProperty;
}
return super.findProperty(key, deep, isScope, start);
}
@@ -295,14 +280,14 @@
private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
final MethodHandle expressionGuard = expressionGuard(name, owner);
- final MethodHandle filterGuardReceiver = filterGuardReceiver(newLink, WITHSCOPEFILTER);
+ final MethodHandle filteredGuard = filterGuardReceiver(newLink, WITHSCOPEFILTER);
return link.replaceMethods(
filterReceiver(
newLink.getInvocation(),
WITHSCOPEFILTER),
NashornGuards.combineGuards(
expressionGuard,
- filterGuardReceiver));
+ filteredGuard));
}
private static MethodHandle filterGuardReceiver(final GuardedInvocation link, final MethodHandle receiverFilter) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Thu Jul 28 16:08:18 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Thu Jul 28 16:44:11 2016 +0000
@@ -140,7 +140,7 @@
if (!needsGuard(property, desc)) {
return null;
}
- if (NashornCallSiteDescriptor.isScope(desc)) {
+ if (NashornCallSiteDescriptor.isScope(desc) && sobj.isScope()) {
if (property != null && property.isBound() && !property.canChangeType()) {
// This is a declared top level variables in main script or eval, use identity guard.
return getIdentityGuard(sobj);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties Thu Jul 28 16:08:18 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties Thu Jul 28 16:44:11 2016 +0000
@@ -135,3 +135,41 @@
Math.sqrt=returns an approximation to the square root of given argument
Math.tan=returns an approximation to the tangent of given argument
+
+String.fromCharCode=returns a string value containing the characters corresponding to the sequence of unicode values given as arguments
+
+String.prototype.toString=returns string value of calling object, returns TypeError if calling object is not a string object
+
+String.prototype.valueOf=returns string value of calling object, returns TypeError if calling object is not a string object
+
+String.prototype.charAt=returns string value representing the character at the index given as argument, empty string if the index is out of range
+
+String.prototype.concat=returns the string resulting from appending the argument string value to the calling object
+
+String.prototype.indexOf=returns the index of first occurrence of specified string, starting the search from position given as argument, returns -1 if the string is not found
+
+String.prototype.lastIndexOf=returns the index of last occurrence of specified string, searching backwards from position given as argument, returns -1 if the string is not found
+
+String.prototype.localeCompare=returns negative, zero, or positive value if calling string value comes before, equal, or after argument string value in the locale-sensitive sort order
+
+String.prototype.match=returns an array containing entire match result when matching calling string value against regular expression given as argument
+
+String.prototype.replace=returns a new string with some or all matches of pattern argument replaced by the given replacement argument
+
+String.prototype.search=returns index of the first occurrence of the match between regular expression given as argument and the calling string, returns -1 if not found
+
+String.prototype.slice=returns a new string by extracting a section of the string according to given arguments
+
+String.prototype.split=returns an array of strings split at each point where the separator given as argument occurs in the calling string, number of array elements is limited by second argument
+
+String.prototype.substring=returns a new string value extracted from the calling string starting from first argument position to position before the second argument position
+
+String.prototype.toLowerCase=returns a new string representing the calling string value converted to lower case
+
+String.prototype.toLocaleLowerCase=returns a new string representing the calling string value converted to lower case according to any locale specific case mappings
+
+String.prototype.toUpperCase=returns a new string representing the calling string value converted to upper case
+
+String.prototype.toLocaleUpperCase=returns a new string representing the calling string value converted to upper case according to any locale specific case mappings
+
+String.prototype.trim=returns a new string representing the calling string with white space removed from both ends
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8160034.js Thu Jul 28 16:44:11 2016 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, 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-8160034.js: The `this` value in the `with` is broken by the repetition of a function call
+ *
+ * @test
+ * @option --unstable-relink-threshold=4
+ * @run
+ */
+
+
+var bar = "BAR";
+
+function Foo() {
+ this.bar = "bar";
+ this.baz = "baz";
+}
+
+function foo_proto_h() {
+ print(this.bar);
+ delete Foo.prototype._h;
+}
+
+function foo_proto_e() {
+ print(this.baz);
+}
+
+function _h() {
+ print(this.bar);
+ Foo.prototype._h = foo_proto_h;
+}
+
+Foo.prototype._e = foo_proto_e;
+Foo.prototype._h = foo_proto_h;
+
+
+var fn = new Function("with(this) { _h(); _e(); }");
+
+for (var i = 0; i < 20; i++) {
+ fn.call(new Foo());
+}
+
+for (var i = 0; i < 20; i++) {
+ foo = new Foo();
+ foo['e' + Math.random()] = 1; // force new map
+ fn.call(foo);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8160034.js.EXPECTED Thu Jul 28 16:44:11 2016 +0000
@@ -0,0 +1,80 @@
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz
+bar
+baz
+BAR
+baz