8016618: script mirror object access should be improved

Fri, 14 Jun 2013 21:16:14 +0530

author
sundar
date
Fri, 14 Jun 2013 21:16:14 +0530
changeset 350
3d947baa33cc
parent 349
3efa56767847
child 351
a2fa56222fa2

8016618: script mirror object access should be improved
Reviewed-by: jlaskey, lagergren

src/jdk/nashorn/api/scripting/ScriptObjectMirror.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/BreakableNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptRuntime.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8016618.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8016618.js.EXPECTED file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Jun 14 13:53:40 2013 +0200
     1.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Jun 14 21:16:14 2013 +0530
     1.3 @@ -342,6 +342,184 @@
     1.4          });
     1.5      }
     1.6  
     1.7 +    // Support for ECMAScript Object API on mirrors
     1.8 +
     1.9 +    /**
    1.10 +     * Return the __proto__ of this object.
    1.11 +     * @return __proto__ object.
    1.12 +     */
    1.13 +    public Object getProto() {
    1.14 +        return inGlobal(new Callable<Object>() {
    1.15 +            @Override public Object call() {
    1.16 +                return wrap(getScriptObject().getProto(), global);
    1.17 +            }
    1.18 +        });
    1.19 +    }
    1.20 +
    1.21 +    /**
    1.22 +     * ECMA 8.12.1 [[GetOwnProperty]] (P)
    1.23 +     *
    1.24 +     * @param key property key
    1.25 +     *
    1.26 +     * @return Returns the Property Descriptor of the named own property of this
    1.27 +     * object, or undefined if absent.
    1.28 +     */
    1.29 +    public Object getOwnPropertyDescriptor(final String key) {
    1.30 +        return inGlobal(new Callable<Object>() {
    1.31 +            @Override public Object call() {
    1.32 +                return wrap(getScriptObject().getOwnPropertyDescriptor(key), global);
    1.33 +            }
    1.34 +        });
    1.35 +    }
    1.36 +
    1.37 +    /**
    1.38 +     * return an array of own property keys associated with the object.
    1.39 +     *
    1.40 +     * @param all True if to include non-enumerable keys.
    1.41 +     * @return Array of keys.
    1.42 +     */
    1.43 +    public String[] getOwnKeys(final boolean all) {
    1.44 +        return inGlobal(new Callable<String[]>() {
    1.45 +            @Override public String[] call() {
    1.46 +                return getScriptObject().getOwnKeys(all);
    1.47 +            }
    1.48 +        });
    1.49 +    }
    1.50 +
    1.51 +    /**
    1.52 +     * Flag this script object as non extensible
    1.53 +     *
    1.54 +     * @return the object after being made non extensible
    1.55 +     */
    1.56 +    public ScriptObjectMirror preventExtensions() {
    1.57 +        return inGlobal(new Callable<ScriptObjectMirror>() {
    1.58 +            @Override public ScriptObjectMirror call() {
    1.59 +                getScriptObject().preventExtensions();
    1.60 +                return ScriptObjectMirror.this;
    1.61 +            }
    1.62 +        });
    1.63 +    }
    1.64 +
    1.65 +    /**
    1.66 +     * Check if this script object is extensible
    1.67 +     * @return true if extensible
    1.68 +     */
    1.69 +    public boolean isExtensible() {
    1.70 +        return inGlobal(new Callable<Boolean>() {
    1.71 +            @Override public Boolean call() {
    1.72 +                return getScriptObject().isExtensible();
    1.73 +            }
    1.74 +        });
    1.75 +    }
    1.76 +
    1.77 +    /**
    1.78 +     * ECMAScript 15.2.3.8 - seal implementation
    1.79 +     * @return the sealed script object
    1.80 +     */
    1.81 +    public ScriptObjectMirror seal() {
    1.82 +        return inGlobal(new Callable<ScriptObjectMirror>() {
    1.83 +            @Override public ScriptObjectMirror call() {
    1.84 +                getScriptObject().seal();
    1.85 +                return ScriptObjectMirror.this;
    1.86 +            }
    1.87 +        });
    1.88 +    }
    1.89 +
    1.90 +    /**
    1.91 +     * Check whether this script object is sealed
    1.92 +     * @return true if sealed
    1.93 +     */
    1.94 +    public boolean isSealed() {
    1.95 +        return inGlobal(new Callable<Boolean>() {
    1.96 +            @Override public Boolean call() {
    1.97 +                return getScriptObject().isSealed();
    1.98 +            }
    1.99 +        });
   1.100 +    }
   1.101 +
   1.102 +    /**
   1.103 +     * ECMA 15.2.39 - freeze implementation. Freeze this script object
   1.104 +     * @return the frozen script object
   1.105 +     */
   1.106 +    public ScriptObjectMirror freeze() {
   1.107 +        return inGlobal(new Callable<ScriptObjectMirror>() {
   1.108 +            @Override public ScriptObjectMirror call() {
   1.109 +                getScriptObject().freeze();
   1.110 +                return ScriptObjectMirror.this;
   1.111 +            }
   1.112 +        });
   1.113 +    }
   1.114 +
   1.115 +    /**
   1.116 +     * Check whether this script object is frozen
   1.117 +     * @return true if frozen
   1.118 +     */
   1.119 +    public boolean isFrozen() {
   1.120 +        return inGlobal(new Callable<Boolean>() {
   1.121 +            @Override public Boolean call() {
   1.122 +                return getScriptObject().isFrozen();
   1.123 +            }
   1.124 +        });
   1.125 +    }
   1.126 +
   1.127 +    // ECMAScript instanceof check
   1.128 +
   1.129 +    /**
   1.130 +     * Checking whether a script object is an instance of another by
   1.131 +     * walking the proto chain
   1.132 +     *
   1.133 +     * @param instance instace to check
   1.134 +     * @return true if 'instance' is an instance of this object
   1.135 +     */
   1.136 +    public boolean isInstance(final ScriptObjectMirror instance) {
   1.137 +        // if not belongs to my global scope, return false
   1.138 +        if (instance == null || global != instance.global) {
   1.139 +            return false;
   1.140 +        }
   1.141 +
   1.142 +        return inGlobal(new Callable<Boolean>() {
   1.143 +            @Override public Boolean call() {
   1.144 +                return getScriptObject().isInstance(instance.getScriptObject());
   1.145 +            }
   1.146 +        });
   1.147 +    }
   1.148 +
   1.149 +    /**
   1.150 +     * Utility to check if given object is ECMAScript undefined value
   1.151 +     *
   1.152 +     * @param obj object to check
   1.153 +     * @return true if 'obj' is ECMAScript undefined value
   1.154 +     */
   1.155 +    public static boolean isUndefined(final Object obj) {
   1.156 +        return obj == ScriptRuntime.UNDEFINED;
   1.157 +    }
   1.158 +
   1.159 +    /**
   1.160 +     * is this a function object?
   1.161 +     *
   1.162 +     * @return if this mirror wraps a ECMAScript function instance
   1.163 +     */
   1.164 +    public boolean isFunction() {
   1.165 +        return getScriptObject() instanceof ScriptFunction;
   1.166 +    }
   1.167 +
   1.168 +    /**
   1.169 +     * is this a 'use strict' function object?
   1.170 +     *
   1.171 +     * @return true if this mirror represents a ECMAScript 'use strict' function
   1.172 +     */
   1.173 +    public boolean isStrictFunction() {
   1.174 +        return isFunction() && ((ScriptFunction)getScriptObject()).isStrict();
   1.175 +    }
   1.176 +
   1.177 +    /**
   1.178 +     * is this an array object?
   1.179 +     *
   1.180 +     * @return if this mirror wraps a ECMAScript array object
   1.181 +     */
   1.182 +    public boolean isArray() {
   1.183 +        return getScriptObject().isArray();
   1.184 +    }
   1.185  
   1.186      // These are public only so that Context can access these.
   1.187  
     2.1 --- a/src/jdk/nashorn/internal/ir/BreakableNode.java	Fri Jun 14 13:53:40 2013 +0200
     2.2 +++ b/src/jdk/nashorn/internal/ir/BreakableNode.java	Fri Jun 14 21:16:14 2013 +0530
     2.3 @@ -86,7 +86,7 @@
     2.4  
     2.5      /**
     2.6       * Return the labels associated with this node. Breakable nodes that
     2.7 -     * aren't LoopNodes only have a break label -> the location immediately
     2.8 +     * aren't LoopNodes only have a break label - the location immediately
     2.9       * afterwards the node in code
    2.10       * @return list of labels representing locations around this node
    2.11       */
     3.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java	Fri Jun 14 13:53:40 2013 +0200
     3.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Fri Jun 14 21:16:14 2013 +0530
     3.3 @@ -39,6 +39,7 @@
     3.4  import java.util.Comparator;
     3.5  import java.util.Iterator;
     3.6  import java.util.List;
     3.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
     3.8  import jdk.nashorn.internal.objects.annotations.Attribute;
     3.9  import jdk.nashorn.internal.objects.annotations.Constructor;
    3.10  import jdk.nashorn.internal.objects.annotations.Function;
    3.11 @@ -291,7 +292,8 @@
    3.12      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    3.13      public static Object isArray(final Object self, final Object arg) {
    3.14          return isArray(arg) || (arg == Global.instance().getArrayPrototype())
    3.15 -                || (arg instanceof NativeRegExpExecResult);
    3.16 +                || (arg instanceof NativeRegExpExecResult)
    3.17 +                || (arg instanceof ScriptObjectMirror && ((ScriptObjectMirror)arg).isArray());
    3.18      }
    3.19  
    3.20      /**
     4.1 --- a/src/jdk/nashorn/internal/objects/NativeFunction.java	Fri Jun 14 13:53:40 2013 +0200
     4.2 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java	Fri Jun 14 21:16:14 2013 +0530
     4.3 @@ -29,6 +29,7 @@
     4.4  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
     4.5  
     4.6  import java.util.List;
     4.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
     4.8  import jdk.nashorn.internal.objects.annotations.Attribute;
     4.9  import jdk.nashorn.internal.objects.annotations.Constructor;
    4.10  import jdk.nashorn.internal.objects.annotations.Function;
    4.11 @@ -102,6 +103,16 @@
    4.12              list.toArray(args = new Object[list.size()]);
    4.13          } else if (array == null || array == UNDEFINED) {
    4.14              args = ScriptRuntime.EMPTY_ARRAY;
    4.15 +        } else if (array instanceof ScriptObjectMirror) {
    4.16 +            // look for array-like ScriptObjectMirror object
    4.17 +            final ScriptObjectMirror mirror = (ScriptObjectMirror)array;
    4.18 +            final Object       len  = mirror.containsKey("length")? mirror.getMember("length") : Integer.valueOf(0);
    4.19 +            final int n = (int)JSType.toUint32(len);
    4.20 +
    4.21 +            args = new Object[n];
    4.22 +            for (int i = 0; i < args.length; i++) {
    4.23 +                args[i] = mirror.containsKey(i)? mirror.getSlot(i) : UNDEFINED;
    4.24 +            }
    4.25          } else {
    4.26              throw typeError("function.apply.expects.array");
    4.27          }
     5.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Jun 14 13:53:40 2013 +0200
     5.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Jun 14 21:16:14 2013 +0530
     5.3 @@ -28,11 +28,13 @@
     5.4  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
     5.5  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
     5.6  
     5.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
     5.8  import jdk.nashorn.internal.objects.annotations.Attribute;
     5.9  import jdk.nashorn.internal.objects.annotations.Constructor;
    5.10  import jdk.nashorn.internal.objects.annotations.Function;
    5.11  import jdk.nashorn.internal.objects.annotations.ScriptClass;
    5.12  import jdk.nashorn.internal.objects.annotations.Where;
    5.13 +import jdk.nashorn.internal.runtime.ECMAException;
    5.14  import jdk.nashorn.internal.runtime.JSType;
    5.15  import jdk.nashorn.internal.runtime.ScriptFunction;
    5.16  import jdk.nashorn.internal.runtime.ScriptObject;
    5.17 @@ -54,6 +56,10 @@
    5.18      private NativeObject() {
    5.19      }
    5.20  
    5.21 +    private static ECMAException notAnObject(final Object obj) {
    5.22 +        return typeError("not.an.object", ScriptRuntime.safeToString(obj));
    5.23 +    }
    5.24 +
    5.25      /**
    5.26       * ECMA 15.2.3.2 Object.getPrototypeOf ( O )
    5.27       *
    5.28 @@ -63,9 +69,13 @@
    5.29       */
    5.30      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    5.31      public static Object getPrototypeOf(final Object self, final Object obj) {
    5.32 -        Global.checkObject(obj);
    5.33 -
    5.34 -        return ((ScriptObject)obj).getProto();
    5.35 +        if (obj instanceof ScriptObject) {
    5.36 +            return ((ScriptObject)obj).getProto();
    5.37 +        } else if (obj instanceof ScriptObjectMirror) {
    5.38 +            return ((ScriptObjectMirror)obj).getProto();
    5.39 +        } else {
    5.40 +            throw notAnObject(obj);
    5.41 +        }
    5.42      }
    5.43  
    5.44      /**
    5.45 @@ -78,12 +88,19 @@
    5.46       */
    5.47      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    5.48      public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
    5.49 -        Global.checkObject(obj);
    5.50 +        if (obj instanceof ScriptObject) {
    5.51 +            final String       key  = JSType.toString(prop);
    5.52 +            final ScriptObject sobj = (ScriptObject)obj;
    5.53  
    5.54 -        final String       key  = JSType.toString(prop);
    5.55 -        final ScriptObject sobj = (ScriptObject)obj;
    5.56 +            return sobj.getOwnPropertyDescriptor(key);
    5.57 +        } else if (obj instanceof ScriptObjectMirror) {
    5.58 +            final String       key  = JSType.toString(prop);
    5.59 +            final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
    5.60  
    5.61 -        return sobj.getOwnPropertyDescriptor(key);
    5.62 +            return sobjMirror.getOwnPropertyDescriptor(key);
    5.63 +        } else {
    5.64 +            throw notAnObject(obj);
    5.65 +        }
    5.66      }
    5.67  
    5.68      /**
    5.69 @@ -95,9 +112,13 @@
    5.70       */
    5.71      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    5.72      public static Object getOwnPropertyNames(final Object self, final Object obj) {
    5.73 -        Global.checkObject(obj);
    5.74 -
    5.75 -        return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
    5.76 +        if (obj instanceof ScriptObject) {
    5.77 +            return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
    5.78 +        } else if (obj instanceof ScriptObjectMirror) {
    5.79 +            return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true));
    5.80 +        } else {
    5.81 +            throw notAnObject(obj);
    5.82 +        }
    5.83      }
    5.84  
    5.85      /**
    5.86 @@ -175,8 +196,13 @@
    5.87       */
    5.88      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    5.89      public static Object seal(final Object self, final Object obj) {
    5.90 -        Global.checkObject(obj);
    5.91 -        return ((ScriptObject)obj).seal();
    5.92 +        if (obj instanceof ScriptObject) {
    5.93 +            return ((ScriptObject)obj).seal();
    5.94 +        } else if (obj instanceof ScriptObjectMirror) {
    5.95 +            return ((ScriptObjectMirror)obj).seal();
    5.96 +        } else {
    5.97 +            throw notAnObject(obj);
    5.98 +        }
    5.99      }
   5.100  
   5.101  
   5.102 @@ -189,8 +215,13 @@
   5.103       */
   5.104      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.105      public static Object freeze(final Object self, final Object obj) {
   5.106 -        Global.checkObject(obj);
   5.107 -        return ((ScriptObject)obj).freeze();
   5.108 +        if (obj instanceof ScriptObject) {
   5.109 +            return ((ScriptObject)obj).freeze();
   5.110 +        } else if (obj instanceof ScriptObjectMirror) {
   5.111 +            return ((ScriptObjectMirror)obj).freeze();
   5.112 +        } else {
   5.113 +            throw notAnObject(obj);
   5.114 +        }
   5.115      }
   5.116  
   5.117      /**
   5.118 @@ -202,8 +233,13 @@
   5.119       */
   5.120      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.121      public static Object preventExtensions(final Object self, final Object obj) {
   5.122 -        Global.checkObject(obj);
   5.123 -        return ((ScriptObject)obj).preventExtensions();
   5.124 +        if (obj instanceof ScriptObject) {
   5.125 +            return ((ScriptObject)obj).preventExtensions();
   5.126 +        } else if (obj instanceof ScriptObjectMirror) {
   5.127 +            return ((ScriptObjectMirror)obj).preventExtensions();
   5.128 +        } else {
   5.129 +            throw notAnObject(obj);
   5.130 +        }
   5.131      }
   5.132  
   5.133      /**
   5.134 @@ -215,8 +251,13 @@
   5.135       */
   5.136      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.137      public static Object isSealed(final Object self, final Object obj) {
   5.138 -        Global.checkObject(obj);
   5.139 -        return ((ScriptObject)obj).isSealed();
   5.140 +        if (obj instanceof ScriptObject) {
   5.141 +            return ((ScriptObject)obj).isSealed();
   5.142 +        } else if (obj instanceof ScriptObjectMirror) {
   5.143 +            return ((ScriptObjectMirror)obj).isSealed();
   5.144 +        } else {
   5.145 +            throw notAnObject(obj);
   5.146 +        }
   5.147      }
   5.148  
   5.149      /**
   5.150 @@ -228,8 +269,13 @@
   5.151       */
   5.152      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.153      public static Object isFrozen(final Object self, final Object obj) {
   5.154 -        Global.checkObject(obj);
   5.155 -        return ((ScriptObject)obj).isFrozen();
   5.156 +        if (obj instanceof ScriptObject) {
   5.157 +            return ((ScriptObject)obj).isFrozen();
   5.158 +        } else if (obj instanceof ScriptObjectMirror) {
   5.159 +            return ((ScriptObjectMirror)obj).isFrozen();
   5.160 +        } else {
   5.161 +            throw notAnObject(obj);
   5.162 +        }
   5.163      }
   5.164  
   5.165      /**
   5.166 @@ -241,8 +287,13 @@
   5.167       */
   5.168      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.169      public static Object isExtensible(final Object self, final Object obj) {
   5.170 -        Global.checkObject(obj);
   5.171 -        return ((ScriptObject)obj).isExtensible();
   5.172 +        if (obj instanceof ScriptObject) {
   5.173 +            return ((ScriptObject)obj).isExtensible();
   5.174 +        } else if (obj instanceof ScriptObjectMirror) {
   5.175 +            return ((ScriptObjectMirror)obj).isExtensible();
   5.176 +        } else {
   5.177 +            throw notAnObject(obj);
   5.178 +        }
   5.179      }
   5.180  
   5.181      /**
   5.182 @@ -254,9 +305,15 @@
   5.183       */
   5.184      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   5.185      public static Object keys(final Object self, final Object obj) {
   5.186 -        Global.checkObject(obj);
   5.187 -        final ScriptObject sobj = (ScriptObject)obj;
   5.188 -        return new NativeArray(sobj.getOwnKeys(false));
   5.189 +        if (obj instanceof ScriptObject) {
   5.190 +            final ScriptObject sobj = (ScriptObject)obj;
   5.191 +            return new NativeArray(sobj.getOwnKeys(false));
   5.192 +        } else if (obj instanceof ScriptObjectMirror) {
   5.193 +            final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
   5.194 +            return new NativeArray(sobjMirror.getOwnKeys(false));
   5.195 +        } else {
   5.196 +            throw notAnObject(obj);
   5.197 +        }
   5.198      }
   5.199  
   5.200      /**
     6.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Fri Jun 14 13:53:40 2013 +0200
     6.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Fri Jun 14 21:16:14 2013 +0530
     6.3 @@ -46,6 +46,7 @@
     6.4  import java.security.Permissions;
     6.5  import java.security.PrivilegedAction;
     6.6  import java.security.ProtectionDomain;
     6.7 +import java.util.Map;
     6.8  import jdk.internal.org.objectweb.asm.ClassReader;
     6.9  import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
    6.10  import jdk.nashorn.api.scripting.ScriptObjectMirror;
    6.11 @@ -482,6 +483,13 @@
    6.12                  final String name   = JSType.toString(sobj.get("name"));
    6.13                  source = new Source(name, script);
    6.14              }
    6.15 +        } else if (src instanceof Map) {
    6.16 +            final Map map = (Map)src;
    6.17 +            if (map.containsKey("script") && map.containsKey("name")) {
    6.18 +                final String script = JSType.toString(map.get("script"));
    6.19 +                final String name   = JSType.toString(map.get("name"));
    6.20 +                source = new Source(name, script);
    6.21 +            }
    6.22          }
    6.23  
    6.24          if (source != null) {
     7.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Jun 14 13:53:40 2013 +0200
     7.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Jun 14 21:16:14 2013 +0530
     7.3 @@ -1108,7 +1108,8 @@
     7.4      }
     7.5  
     7.6      /**
     7.7 -     * return a List of own keys associated with the object.
     7.8 +     * return an array of own property keys associated with the object.
     7.9 +     *
    7.10       * @param all True if to include non-enumerable keys.
    7.11       * @return Array of keys.
    7.12       */
    7.13 @@ -1209,7 +1210,7 @@
    7.14       * the proto chain
    7.15       *
    7.16       * @param instance instace to check
    7.17 -     * @return true if instance of instance
    7.18 +     * @return true if 'instance' is an instance of this object
    7.19       */
    7.20      public boolean isInstance(final ScriptObject instance) {
    7.21          return false;
    7.22 @@ -1382,7 +1383,7 @@
    7.23  
    7.24      /**
    7.25       * Check whether this ScriptObject is frozen
    7.26 -     * @return true if frozed
    7.27 +     * @return true if frozen
    7.28       */
    7.29      public boolean isFrozen() {
    7.30          return getMap().isFrozen();
     8.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Fri Jun 14 13:53:40 2013 +0200
     8.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Fri Jun 14 21:16:14 2013 +0530
     8.3 @@ -825,6 +825,13 @@
     8.4              return ((StaticClass)clazz).getRepresentedClass().isInstance(obj);
     8.5          }
     8.6  
     8.7 +        if (clazz instanceof ScriptObjectMirror) {
     8.8 +            if (obj instanceof ScriptObjectMirror) {
     8.9 +                return ((ScriptObjectMirror)clazz).isInstance((ScriptObjectMirror)obj);
    8.10 +            }
    8.11 +            return false;
    8.12 +        }
    8.13 +
    8.14          throw typeError("instanceof.on.non.object");
    8.15      }
    8.16  
     9.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java	Fri Jun 14 13:53:40 2013 +0200
     9.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java	Fri Jun 14 21:16:14 2013 +0530
     9.3 @@ -26,6 +26,7 @@
     9.4  package jdk.nashorn.internal.runtime.arrays;
     9.5  
     9.6  import java.util.Iterator;
     9.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
     9.8  import jdk.nashorn.internal.runtime.JSType;
     9.9  import jdk.nashorn.internal.runtime.ScriptObject;
    9.10  
    9.11 @@ -125,6 +126,10 @@
    9.12              return new MapIterator((ScriptObject)obj, includeUndefined);
    9.13          }
    9.14  
    9.15 +        if (obj instanceof ScriptObjectMirror) {
    9.16 +            return new ScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
    9.17 +        }
    9.18 +
    9.19          return new EmptyArrayLikeIterator();
    9.20      }
    9.21  
    9.22 @@ -146,6 +151,10 @@
    9.23              return new ReverseMapIterator((ScriptObject)obj, includeUndefined);
    9.24          }
    9.25  
    9.26 +        if (obj instanceof ScriptObjectMirror) {
    9.27 +            return new ReverseScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
    9.28 +        }
    9.29 +
    9.30          assert !obj.getClass().isArray();
    9.31  
    9.32          return new EmptyArrayLikeIterator();
    10.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java	Fri Jun 14 13:53:40 2013 +0200
    10.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java	Fri Jun 14 21:16:14 2013 +0530
    10.3 @@ -27,6 +27,7 @@
    10.4  
    10.5  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    10.6  
    10.7 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
    10.8  import jdk.nashorn.internal.runtime.Context;
    10.9  import jdk.nashorn.internal.runtime.ScriptFunction;
   10.10  import jdk.nashorn.internal.runtime.ScriptRuntime;
   10.11 @@ -96,12 +97,18 @@
   10.12       * @return result of apply
   10.13       */
   10.14      public final T apply() {
   10.15 -        if (!(callbackfn instanceof ScriptFunction)) {
   10.16 +        final boolean strict;
   10.17 +        if (callbackfn instanceof ScriptFunction) {
   10.18 +            strict = ((ScriptFunction)callbackfn).isStrict();
   10.19 +        } else if (callbackfn instanceof ScriptObjectMirror &&
   10.20 +            ((ScriptObjectMirror)callbackfn).isFunction()) {
   10.21 +            strict = ((ScriptObjectMirror)callbackfn).isStrictFunction();
   10.22 +        } else {
   10.23              throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
   10.24          }
   10.25 -        final ScriptFunction func = ((ScriptFunction)callbackfn);
   10.26 +
   10.27          // for non-strict callback, need to translate undefined thisArg to be global object
   10.28 -        thisArg = (thisArg == ScriptRuntime.UNDEFINED && !func.isStrict()) ? Context.getGlobal() : thisArg;
   10.29 +        thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
   10.30  
   10.31          applyLoopBegin(iter);
   10.32          final boolean reverse = iter.isReverse();
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java	Fri Jun 14 21:16:14 2013 +0530
    11.3 @@ -0,0 +1,56 @@
    11.4 +/*
    11.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Oracle designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Oracle in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.25 + * or visit www.oracle.com if you need additional information or have any
   11.26 + * questions.
   11.27 + */
   11.28 +
   11.29 +package jdk.nashorn.internal.runtime.arrays;
   11.30 +
   11.31 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
   11.32 +import jdk.nashorn.internal.runtime.JSType;
   11.33 +
   11.34 +/**
   11.35 + * Reverse iterator over a ScriptObjectMirror
   11.36 + */
   11.37 +final class ReverseScriptObjectMirrorIterator extends ScriptObjectMirrorIterator {
   11.38 +
   11.39 +    ReverseScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) {
   11.40 +        super(obj, includeUndefined);
   11.41 +        this.index = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0) - 1;
   11.42 +    }
   11.43 +
   11.44 +    @Override
   11.45 +    public boolean isReverse() {
   11.46 +        return true;
   11.47 +    }
   11.48 +
   11.49 +    @Override
   11.50 +    protected boolean indexInArray() {
   11.51 +        return index >= 0;
   11.52 +    }
   11.53 +
   11.54 +    @Override
   11.55 +    protected long bumpIndex() {
   11.56 +        return index--;
   11.57 +    }
   11.58 +}
   11.59 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java	Fri Jun 14 21:16:14 2013 +0530
    12.3 @@ -0,0 +1,81 @@
    12.4 +/*
    12.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Oracle designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Oracle in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.25 + * or visit www.oracle.com if you need additional information or have any
   12.26 + * questions.
   12.27 + */
   12.28 +
   12.29 +package jdk.nashorn.internal.runtime.arrays;
   12.30 +
   12.31 +import java.util.NoSuchElementException;
   12.32 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
   12.33 +import jdk.nashorn.internal.runtime.JSType;
   12.34 +
   12.35 +/**
   12.36 + * Iterator over a ScriptObjectMirror
   12.37 + */
   12.38 +class ScriptObjectMirrorIterator extends ArrayLikeIterator<Object> {
   12.39 +
   12.40 +    protected final ScriptObjectMirror obj;
   12.41 +    private final long length;
   12.42 +
   12.43 +    ScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) {
   12.44 +        super(includeUndefined);
   12.45 +        this.obj    = obj;
   12.46 +        this.length = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0);
   12.47 +        this.index  = 0;
   12.48 +    }
   12.49 +
   12.50 +    protected boolean indexInArray() {
   12.51 +        return index < length;
   12.52 +    }
   12.53 +
   12.54 +    @Override
   12.55 +    public long getLength() {
   12.56 +        return length;
   12.57 +    }
   12.58 +
   12.59 +    @Override
   12.60 +    public boolean hasNext() {
   12.61 +        if (length == 0L) {
   12.62 +            return false; //return empty string if toUint32(length) == 0
   12.63 +        }
   12.64 +
   12.65 +        while (indexInArray()) {
   12.66 +            if (obj.containsKey(index) || includeUndefined) {
   12.67 +                break;
   12.68 +            }
   12.69 +            bumpIndex();
   12.70 +        }
   12.71 +
   12.72 +        return indexInArray();
   12.73 +    }
   12.74 +
   12.75 +    @Override
   12.76 +    public Object next() {
   12.77 +        if (indexInArray()) {
   12.78 +            return obj.get(bumpIndex());
   12.79 +        }
   12.80 +
   12.81 +        throw new NoSuchElementException();
   12.82 +    }
   12.83 +}
   12.84 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/script/basic/JDK-8016618.js	Fri Jun 14 21:16:14 2013 +0530
    13.3 @@ -0,0 +1,132 @@
    13.4 +/*
    13.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + * 
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + * 
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + * 
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + * 
   13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.23 + * or visit www.oracle.com if you need additional information or have any
   13.24 + * questions.
   13.25 + */
   13.26 +
   13.27 +/**
   13.28 + * JDK-8016618: script mirror object access should be improved
   13.29 + *
   13.30 + * @test
   13.31 + * @option -scripting
   13.32 + * @option -strict
   13.33 + * @run
   13.34 + */
   13.35 +
   13.36 +var global = loadWithNewGlobal({
   13.37 +    name: "code",
   13.38 +    script: <<EOF
   13.39 +var x = 33;
   13.40 +
   13.41 +function func(x, y) {
   13.42 +    print('func.x = ' + x);
   13.43 +    print('func.x = ' + y)
   13.44 +}; 
   13.45 +
   13.46 +var obj = {
   13.47 +    foo: 'hello',
   13.48 +    bar: 42
   13.49 +};
   13.50 +
   13.51 +Object.defineProperty(obj, "bar",
   13.52 +    { enumerable: false, writable: false });
   13.53 +
   13.54 +// return global
   13.55 +this;
   13.56 +EOF
   13.57 +});
   13.58 +
   13.59 +// load on mirror with local object as argument
   13.60 +global.load({ 
   13.61 +    name: "code",
   13.62 +    script: "print('x = ' + x)"
   13.63 +});
   13.64 +
   13.65 +function f() {
   13.66 +    // mirror function called with local arguments
   13.67 +    global.func.apply(obj, arguments);
   13.68 +}
   13.69 +
   13.70 +f(23, "hello");
   13.71 +
   13.72 +var fObject = global.eval("Object");
   13.73 +
   13.74 +// instanceof on mirrors
   13.75 +print("global instanceof fObject? " + (global instanceof fObject));
   13.76 +
   13.77 +// Object API on mirrors
   13.78 +
   13.79 +var desc = Object.getOwnPropertyDescriptor(global, "x");
   13.80 +print("x is wriable ? " + desc.writable);
   13.81 +print("x value = " + desc.value);
   13.82 +
   13.83 +var proto = Object.getPrototypeOf(global);
   13.84 +print("global's __proto__ " + proto);
   13.85 +
   13.86 +var obj = global.obj;
   13.87 +var keys = Object.keys(obj);
   13.88 +print("Object.keys on obj");
   13.89 +for (var i in keys) {
   13.90 +    print(keys[i]);
   13.91 +}
   13.92 +
   13.93 +print("Object.getOwnProperties on obj");
   13.94 +var keys = Object.getOwnPropertyNames(obj);
   13.95 +for (var i in keys) {
   13.96 +  print(keys[i]);
   13.97 +}
   13.98 +
   13.99 +// mirror array access
  13.100 +var array = global.eval("[334, 55, 65]");
  13.101 +Array.prototype.forEach.call(array, function(elem) {
  13.102 +    print("forEach " + elem)
  13.103 +});
  13.104 +
  13.105 +print("reduceRight " + Array.prototype.reduceRight.call(array,
  13.106 +    function(previousValue, currentValue, index, array) {
  13.107 +        print("reduceRight cur value " + currentValue);
  13.108 +        return previousValue + currentValue;
  13.109 +}, 0));
  13.110 +
  13.111 +print("reduce " + Array.prototype.reduce.call(array,
  13.112 +    function(previousValue, currentValue, index, array) {
  13.113 +        print("reduce cur value " + currentValue);
  13.114 +        return previousValue + currentValue;
  13.115 +}, 0));
  13.116 +
  13.117 +print("forEach");
  13.118 +Array.prototype.forEach.call(array, function(o) {
  13.119 +   print(o);
  13.120 +});
  13.121 +
  13.122 +print("Array.isArray(array)? " + Array.isArray(array));
  13.123 +
  13.124 +// try to write to a non-writable property of mirror
  13.125 +try {
  13.126 +   obj.bar = 33;
  13.127 +} catch (e) {
  13.128 +   print(e);
  13.129 +}
  13.130 +
  13.131 +// mirror function called with local callback
  13.132 +print("forEach on mirror");
  13.133 +array.forEach(function(toto) {
  13.134 +    print(toto);
  13.135 +});
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/script/basic/JDK-8016618.js.EXPECTED	Fri Jun 14 21:16:14 2013 +0530
    14.3 @@ -0,0 +1,33 @@
    14.4 +x = 33
    14.5 +func.x = 23
    14.6 +func.x = hello
    14.7 +global instanceof fObject? true
    14.8 +x is wriable ? true
    14.9 +x value = 33
   14.10 +global's __proto__ [object Object]
   14.11 +Object.keys on obj
   14.12 +foo
   14.13 +Object.getOwnProperties on obj
   14.14 +foo
   14.15 +bar
   14.16 +forEach 334
   14.17 +forEach 55
   14.18 +forEach 65
   14.19 +reduceRight cur value 65
   14.20 +reduceRight cur value 55
   14.21 +reduceRight cur value 334
   14.22 +reduceRight 454
   14.23 +reduce cur value 334
   14.24 +reduce cur value 55
   14.25 +reduce cur value 65
   14.26 +reduce 454
   14.27 +forEach
   14.28 +334
   14.29 +55
   14.30 +65
   14.31 +Array.isArray(array)? true
   14.32 +TypeError: "bar" is not a writable property of [object Object]
   14.33 +forEach on mirror
   14.34 +334
   14.35 +55
   14.36 +65

mercurial