8046013: TypeError: Cannot apply "with" to non script object
Reviewed-by: lagergren, hannesw
This commit is contained in:
parent
8f69a3e4a8
commit
4b428d5833
nashorn
src/jdk/nashorn/internal
test
@ -716,6 +716,32 @@ public final class NativeObject {
|
||||
return target;
|
||||
}
|
||||
|
||||
/*
|
||||
* Binds the source mirror object's properties to the target object. Binding
|
||||
* properties allows two-way read/write for the properties of the source object.
|
||||
* All inherited, enumerable properties are also bound. This method is used to
|
||||
* to make 'with' statement work with ScriptObjectMirror as scope object.
|
||||
*
|
||||
* @param target the target object to which the source object's properties are bound
|
||||
* @param source the source object whose properties are bound to the target
|
||||
* @return the target object after property binding
|
||||
*/
|
||||
public static Object bindAllProperties(final ScriptObject target, final ScriptObjectMirror source) {
|
||||
final Set<String> keys = source.keySet();
|
||||
// make accessor properties using dynamic invoker getters and setters
|
||||
final AccessorProperty[] props = new AccessorProperty[keys.size()];
|
||||
int idx = 0;
|
||||
for (String name : keys) {
|
||||
final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
|
||||
final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
|
||||
props[idx] = AccessorProperty.create(name, 0, getter, setter);
|
||||
idx++;
|
||||
}
|
||||
|
||||
target.addBoundProperties(source, props);
|
||||
return target;
|
||||
}
|
||||
|
||||
private static void bindBeanProperties(final ScriptObject targetObj, final Object source,
|
||||
final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames,
|
||||
final Collection<String> methodNames) {
|
||||
|
@ -49,6 +49,7 @@ import jdk.nashorn.internal.codegen.CompilerConstants;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.ir.debug.JSONWriter;
|
||||
import jdk.nashorn.internal.objects.Global;
|
||||
import jdk.nashorn.internal.objects.NativeObject;
|
||||
import jdk.nashorn.internal.parser.Lexer;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
|
||||
@ -478,9 +479,21 @@ public final class ScriptRuntime {
|
||||
throw typeError(global, "cant.apply.with.to.null");
|
||||
}
|
||||
|
||||
final Object wrappedExpr = JSType.toScriptObject(global, expression);
|
||||
if (wrappedExpr instanceof ScriptObject) {
|
||||
return new WithObject(scope, (ScriptObject)wrappedExpr);
|
||||
if (expression instanceof ScriptObjectMirror) {
|
||||
final Object unwrapped = ScriptObjectMirror.unwrap(expression, global);
|
||||
if (unwrapped instanceof ScriptObject) {
|
||||
return new WithObject(scope, (ScriptObject)unwrapped);
|
||||
} else {
|
||||
// foreign ScriptObjectMirror
|
||||
ScriptObject exprObj = global.newObject();
|
||||
NativeObject.bindAllProperties(exprObj, (ScriptObjectMirror)expression);
|
||||
return new WithObject(scope, exprObj);
|
||||
}
|
||||
} else {
|
||||
final Object wrappedExpr = JSType.toScriptObject(global, expression);
|
||||
if (wrappedExpr instanceof ScriptObject) {
|
||||
return new WithObject(scope, (ScriptObject)wrappedExpr);
|
||||
}
|
||||
}
|
||||
|
||||
throw typeError(global, "cant.apply.with.to.non.scriptobject");
|
||||
|
@ -31,6 +31,8 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import jdk.nashorn.api.scripting.AbstractJSObject;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
@ -312,7 +314,22 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static Object bindToExpression(final Object fn, final Object receiver) {
|
||||
return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn;
|
||||
if (fn instanceof ScriptFunction) {
|
||||
return bindToExpression((ScriptFunction) fn, receiver);
|
||||
} else if (fn instanceof ScriptObjectMirror) {
|
||||
final ScriptObjectMirror mirror = (ScriptObjectMirror)fn;
|
||||
if (mirror.isFunction()) {
|
||||
// We need to make sure correct 'this' is used for calls with Ident call
|
||||
// expressions. We do so here using an AbstractJSObject instance.
|
||||
return new AbstractJSObject() {
|
||||
public Object call(final Object thiz, final Object... args) {
|
||||
return mirror.call(withFilterExpression(receiver), args);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
private static Object bindToExpression(final ScriptFunction fn, final Object receiver) {
|
||||
|
57
nashorn/test/script/basic/JDK-8046013.js
Normal file
57
nashorn/test/script/basic/JDK-8046013.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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-8046013: TypeError: Cannot apply "with" to non script object
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var obj = loadWithNewGlobal({
|
||||
script: "({ f: 33 })",
|
||||
name: "test"
|
||||
});
|
||||
|
||||
with (obj) {
|
||||
print("f = " + f);
|
||||
}
|
||||
|
||||
var obj2 = loadWithNewGlobal({
|
||||
script: "var obj = Object.create({ foo: 42 }); obj.bar = 'hello'; obj",
|
||||
name: "test2"
|
||||
});
|
||||
|
||||
with (obj2) {
|
||||
print("foo = " + foo);
|
||||
print("bar = " + bar);
|
||||
}
|
||||
|
||||
var obj3 = loadWithNewGlobal({
|
||||
script: "({ f: 33, func: function() { print('this.f =', this.f); } })",
|
||||
name: "test"
|
||||
});
|
||||
|
||||
with(obj3) {
|
||||
func();
|
||||
}
|
4
nashorn/test/script/basic/JDK-8046013.js.EXPECTED
Normal file
4
nashorn/test/script/basic/JDK-8046013.js.EXPECTED
Normal file
@ -0,0 +1,4 @@
|
||||
f = 33
|
||||
foo = 42
|
||||
bar = hello
|
||||
this.f = 33
|
@ -593,6 +593,20 @@ public class ScriptEngineTest {
|
||||
}
|
||||
}
|
||||
|
||||
// @bug 8046013: TypeError: Cannot apply "with" to non script object
|
||||
@Test
|
||||
public void withOnMirrorTest() throws ScriptException {
|
||||
final ScriptEngineManager m = new ScriptEngineManager();
|
||||
final ScriptEngine e = m.getEngineByName("nashorn");
|
||||
|
||||
final Object obj = e.eval("({ foo: 'hello'})");
|
||||
final Object[] arr = new Object[1];
|
||||
arr[0] = obj;
|
||||
e.put("arr", arr);
|
||||
final Object res = e.eval("var res; with(arr[0]) { res = foo; }; res");
|
||||
assertEquals(res, "hello");
|
||||
}
|
||||
|
||||
private static void checkProperty(final ScriptEngine e, final String name)
|
||||
throws ScriptException {
|
||||
final String value = System.getProperty(name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user