Merge
This commit is contained in:
commit
1392897ef0
@ -315,7 +315,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
// 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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import java.util.Set;
|
||||
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 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
|
||||
private final ScriptObject sobj;
|
||||
private final ScriptObject global;
|
||||
private final boolean strict;
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
@ -101,7 +103,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
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 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
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 final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
public void setSlot(final int index, final Object value) {
|
||||
inGlobal(new Callable<Void>() {
|
||||
@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 final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
public void clear() {
|
||||
inGlobal(new Callable<Object>() {
|
||||
@Override public Object call() {
|
||||
sobj.clear();
|
||||
sobj.clear(strict);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -292,7 +294,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
return inGlobal(new Callable<Object>() {
|
||||
@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 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
final boolean globalChanged = (oldGlobal != global);
|
||||
inGlobal(new Callable<Object>() {
|
||||
@Override public Object call() {
|
||||
final boolean strict = global.isStrictContext();
|
||||
for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
|
||||
final Object value = entry.getValue();
|
||||
final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
|
||||
@ -318,7 +319,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
public Object remove(final Object key) {
|
||||
return inGlobal(new Callable<Object>() {
|
||||
@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 final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
public boolean delete(final Object key) {
|
||||
return inGlobal(new Callable<Boolean>() {
|
||||
@Override public Boolean call() {
|
||||
return sobj.delete(unwrap(key, global));
|
||||
return sobj.delete(unwrap(key, global), strict);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -637,10 +638,11 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
|
||||
|
||||
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
|
||||
|
@ -412,6 +412,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
// 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 final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
*/
|
||||
public Global(final Context context) {
|
||||
super(checkAndGetMap(context));
|
||||
this.setContext(context);
|
||||
this.context = context;
|
||||
this.setIsScope();
|
||||
|
||||
final int cacheSize = context.getEnv()._class_cache_size;
|
||||
@ -481,6 +489,16 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
|
||||
// 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) {
|
||||
@ -1765,7 +1783,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
// 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);
|
||||
|
@ -2060,7 +2060,7 @@ loop:
|
||||
case FLOATING:
|
||||
return getLiteral();
|
||||
default:
|
||||
return getIdentifierName();
|
||||
return getIdentifierName().setIsPropertyName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ public final class Context {
|
||||
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
|
||||
|
@ -36,6 +36,18 @@ import jdk.nashorn.internal.runtime.linker.InvokeByName;
|
||||
*/
|
||||
|
||||
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
|
||||
|
@ -198,7 +198,7 @@ public final class NativeJavaPackage extends ScriptObject {
|
||||
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 {
|
||||
|
@ -120,9 +120,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
/** objects proto. */
|
||||
private ScriptObject proto;
|
||||
|
||||
/** Context of the object, lazily cached. */
|
||||
private Context context;
|
||||
|
||||
/** Object flags. */
|
||||
private int flags;
|
||||
|
||||
@ -1042,41 +1039,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
set(key, value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
/**
|
||||
* 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<String> iter = propertyIterator();
|
||||
while (iter.hasNext()) {
|
||||
delete(iter.next(), strict);
|
||||
@ -1568,11 +1537,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
*
|
||||
* @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 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
* (java.util.Map-like method to help ScriptObjectMirror implementation)
|
||||
*
|
||||
* @param otherMap a {@literal <key,value>} 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,25 +1565,15 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
* (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
|
||||
@ -2333,11 +2293,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
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;
|
||||
|
@ -351,35 +351,6 @@ public final class ScriptRuntime {
|
||||
return global;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
@ -400,28 +371,6 @@ public final class ScriptRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -520,9 +469,12 @@ public final class ScriptRuntime {
|
||||
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 final class ScriptRuntime {
|
||||
*/
|
||||
public static ScriptObject closeWith(final ScriptObject scope) {
|
||||
if (scope instanceof WithObject) {
|
||||
return scope.getProto();
|
||||
return ((WithObject)scope).getParentScope();
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
@ -30,26 +30,26 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
* @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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
*/
|
||||
@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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
}
|
||||
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
link = scope.lookup(desc, request);
|
||||
|
||||
if (link != null) {
|
||||
return fixScopeCallSite(link);
|
||||
return fixScopeCallSite(link, name);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -197,11 +194,9 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
*/
|
||||
@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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
* 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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
* 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));
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ type.error.cannot.get.default.string=Cannot get default string value
|
||||
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}
|
||||
|
50
nashorn/test/script/basic/8024180/global_var_delete.js
Normal file
50
nashorn/test/script/basic/8024180/global_var_delete.js
Normal file
@ -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);
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
44
|
||||
ReferenceError: "x" is not defined
|
45
nashorn/test/script/basic/8024180/global_var_shadow.js
Normal file
45
nashorn/test/script/basic/8024180/global_var_shadow.js
Normal file
@ -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' } });
|
||||
|
@ -0,0 +1,2 @@
|
||||
foo
|
||||
toto
|
51
nashorn/test/script/basic/8024180/scope_no_such_prop.js
Normal file
51
nashorn/test/script/basic/8024180/scope_no_such_prop.js
Normal file
@ -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' } });
|
||||
|
@ -0,0 +1,2 @@
|
||||
ReferenceError: user is not defined
|
||||
toto
|
47
nashorn/test/script/basic/8024180/with_expr_prop_add.js
Normal file
47
nashorn/test/script/basic/8024180/with_expr_prop_add.js
Normal file
@ -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();
|
@ -0,0 +1,2 @@
|
||||
global x
|
||||
obj.x
|
@ -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();
|
@ -0,0 +1,2 @@
|
||||
global x
|
||||
p.x
|
36
nashorn/test/script/basic/8024180/with_java_object.js
Normal file
36
nashorn/test/script/basic/8024180/with_java_object.js
Normal file
@ -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);
|
||||
}
|
@ -0,0 +1 @@
|
||||
TypeError: Cannot apply "with" to non script object
|
51
nashorn/test/script/basic/JDK-8024255.js
Normal file
51
nashorn/test/script/basic/JDK-8024255.js
Normal file
@ -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-8024255: When a keyword is used as object property name, the property can not be deleted
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
function check(obj, name) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
if (! desc.configurable) {
|
||||
fail("Property " + name + " is not configurable");
|
||||
}
|
||||
|
||||
if (! (delete obj[name])) {
|
||||
fail("Property " + name + " can not be deleted");
|
||||
}
|
||||
}
|
||||
|
||||
var obj = {
|
||||
default: 344,
|
||||
in: 'hello',
|
||||
if: false,
|
||||
class: 4.223
|
||||
}
|
||||
|
||||
for (var p in obj) {
|
||||
check(obj, p);
|
||||
}
|
@ -64,6 +64,7 @@ public class ContextTest {
|
||||
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 @@ public class ContextTest {
|
||||
assertEquals(sobj.size(), 2);
|
||||
|
||||
// add property
|
||||
sobj.put("zee", "hello");
|
||||
sobj.put("zee", "hello", strict);
|
||||
assertEquals(sobj.get("zee"), "hello");
|
||||
assertEquals(sobj.size(), 3);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user