src/jdk/nashorn/internal/objects/NativeObject.java

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

author
sundar
date
Fri, 14 Jun 2013 21:16:14 +0530
changeset 350
3d947baa33cc
parent 112
267cc4c85160
child 380
80c66d3fd872
permissions
-rw-r--r--

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

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.objects;
    28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    31 import jdk.nashorn.api.scripting.ScriptObjectMirror;
    32 import jdk.nashorn.internal.objects.annotations.Attribute;
    33 import jdk.nashorn.internal.objects.annotations.Constructor;
    34 import jdk.nashorn.internal.objects.annotations.Function;
    35 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    36 import jdk.nashorn.internal.objects.annotations.Where;
    37 import jdk.nashorn.internal.runtime.ECMAException;
    38 import jdk.nashorn.internal.runtime.JSType;
    39 import jdk.nashorn.internal.runtime.ScriptFunction;
    40 import jdk.nashorn.internal.runtime.ScriptObject;
    41 import jdk.nashorn.internal.runtime.ScriptRuntime;
    42 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    44 /**
    45  * ECMA 15.2 Object objects
    46  *
    47  * JavaScript Object constructor/prototype. Note: instances of this class are
    48  * never created. This class is not even a subclass of ScriptObject. But, we use
    49  * this class to generate prototype and constructor for "Object".
    50  *
    51  */
    52 @ScriptClass("Object")
    53 public final class NativeObject {
    54     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    56     private NativeObject() {
    57     }
    59     private static ECMAException notAnObject(final Object obj) {
    60         return typeError("not.an.object", ScriptRuntime.safeToString(obj));
    61     }
    63     /**
    64      * ECMA 15.2.3.2 Object.getPrototypeOf ( O )
    65      *
    66      * @param  self self reference
    67      * @param  obj object to get prototype from
    68      * @return the prototype of an object
    69      */
    70     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    71     public static Object getPrototypeOf(final Object self, final Object obj) {
    72         if (obj instanceof ScriptObject) {
    73             return ((ScriptObject)obj).getProto();
    74         } else if (obj instanceof ScriptObjectMirror) {
    75             return ((ScriptObjectMirror)obj).getProto();
    76         } else {
    77             throw notAnObject(obj);
    78         }
    79     }
    81     /**
    82      * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
    83      *
    84      * @param self  self reference
    85      * @param obj   object from which to get property descriptor for {@code ToString(prop)}
    86      * @param prop  property descriptor
    87      * @return property descriptor
    88      */
    89     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    90     public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
    91         if (obj instanceof ScriptObject) {
    92             final String       key  = JSType.toString(prop);
    93             final ScriptObject sobj = (ScriptObject)obj;
    95             return sobj.getOwnPropertyDescriptor(key);
    96         } else if (obj instanceof ScriptObjectMirror) {
    97             final String       key  = JSType.toString(prop);
    98             final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
   100             return sobjMirror.getOwnPropertyDescriptor(key);
   101         } else {
   102             throw notAnObject(obj);
   103         }
   104     }
   106     /**
   107      * ECMA 15.2.3.4 Object.getOwnPropertyNames ( O )
   108      *
   109      * @param self self reference
   110      * @param obj  object to query for property names
   111      * @return array of property names
   112      */
   113     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   114     public static Object getOwnPropertyNames(final Object self, final Object obj) {
   115         if (obj instanceof ScriptObject) {
   116             return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
   117         } else if (obj instanceof ScriptObjectMirror) {
   118             return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true));
   119         } else {
   120             throw notAnObject(obj);
   121         }
   122     }
   124     /**
   125      * ECMA 15.2.3.5 Object.create ( O [, Properties] )
   126      *
   127      * @param self  self reference
   128      * @param proto prototype object
   129      * @param props properties to define
   130      * @return object created
   131      */
   132     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   133     public static Object create(final Object self, final Object proto, final Object props) {
   134         if (proto != null) {
   135             Global.checkObject(proto);
   136         }
   138         // FIXME: should we create a proper object with correct number of
   139         // properties?
   140         final ScriptObject newObj = Global.newEmptyInstance();
   141         newObj.setProtoCheck(proto);
   142         if (props != UNDEFINED) {
   143             NativeObject.defineProperties(self, newObj, props);
   144         }
   146         return newObj;
   147     }
   149     /**
   150      * ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes )
   151      *
   152      * @param self self reference
   153      * @param obj  object in which to define a property
   154      * @param prop property to define
   155      * @param attr attributes for property descriptor
   156      * @return object
   157      */
   158     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   159     public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
   160         Global.checkObject(obj);
   161         ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true);
   162         return obj;
   163     }
   165     /**
   166      * ECMA 5.2.3.7 Object.defineProperties ( O, Properties )
   167      *
   168      * @param self  self reference
   169      * @param obj   object in which to define properties
   170      * @param props properties
   171      * @return object
   172      */
   173     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   174     public static Object defineProperties(final Object self, final Object obj, final Object props) {
   175         Global.checkObject(obj);
   177         final ScriptObject sobj     = (ScriptObject)obj;
   178         final Object       propsObj = Global.toObject(props);
   180         if (propsObj instanceof ScriptObject) {
   181             final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false);
   182             for (final Object key : keys) {
   183                 final String prop = JSType.toString(key);
   184                 sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true);
   185             }
   186         }
   187         return sobj;
   188     }
   190     /**
   191      * ECMA 15.2.3.8 Object.seal ( O )
   192      *
   193      * @param self self reference
   194      * @param obj  object to seal
   195      * @return sealed object
   196      */
   197     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   198     public static Object seal(final Object self, final Object obj) {
   199         if (obj instanceof ScriptObject) {
   200             return ((ScriptObject)obj).seal();
   201         } else if (obj instanceof ScriptObjectMirror) {
   202             return ((ScriptObjectMirror)obj).seal();
   203         } else {
   204             throw notAnObject(obj);
   205         }
   206     }
   209     /**
   210      * ECMA 15.2.3.9 Object.freeze ( O )
   211      *
   212      * @param self self reference
   213      * @param obj object to freeze
   214      * @return frozen object
   215      */
   216     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   217     public static Object freeze(final Object self, final Object obj) {
   218         if (obj instanceof ScriptObject) {
   219             return ((ScriptObject)obj).freeze();
   220         } else if (obj instanceof ScriptObjectMirror) {
   221             return ((ScriptObjectMirror)obj).freeze();
   222         } else {
   223             throw notAnObject(obj);
   224         }
   225     }
   227     /**
   228      * ECMA 15.2.3.10 Object.preventExtensions ( O )
   229      *
   230      * @param self self reference
   231      * @param obj  object, for which to set the internal extensible property to false
   232      * @return object
   233      */
   234     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   235     public static Object preventExtensions(final Object self, final Object obj) {
   236         if (obj instanceof ScriptObject) {
   237             return ((ScriptObject)obj).preventExtensions();
   238         } else if (obj instanceof ScriptObjectMirror) {
   239             return ((ScriptObjectMirror)obj).preventExtensions();
   240         } else {
   241             throw notAnObject(obj);
   242         }
   243     }
   245     /**
   246      * ECMA 15.2.3.11 Object.isSealed ( O )
   247      *
   248      * @param self self reference
   249      * @param obj check whether an object is sealed
   250      * @return true if sealed, false otherwise
   251      */
   252     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   253     public static Object isSealed(final Object self, final Object obj) {
   254         if (obj instanceof ScriptObject) {
   255             return ((ScriptObject)obj).isSealed();
   256         } else if (obj instanceof ScriptObjectMirror) {
   257             return ((ScriptObjectMirror)obj).isSealed();
   258         } else {
   259             throw notAnObject(obj);
   260         }
   261     }
   263     /**
   264      * ECMA 15.2.3.12 Object.isFrozen ( O )
   265      *
   266      * @param self self reference
   267      * @param obj check whether an object
   268      * @return true if object is frozen, false otherwise
   269      */
   270     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   271     public static Object isFrozen(final Object self, final Object obj) {
   272         if (obj instanceof ScriptObject) {
   273             return ((ScriptObject)obj).isFrozen();
   274         } else if (obj instanceof ScriptObjectMirror) {
   275             return ((ScriptObjectMirror)obj).isFrozen();
   276         } else {
   277             throw notAnObject(obj);
   278         }
   279     }
   281     /**
   282      * ECMA 15.2.3.13 Object.isExtensible ( O )
   283      *
   284      * @param self self reference
   285      * @param obj check whether an object is extensible
   286      * @return true if object is extensible, false otherwise
   287      */
   288     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   289     public static Object isExtensible(final Object self, final Object obj) {
   290         if (obj instanceof ScriptObject) {
   291             return ((ScriptObject)obj).isExtensible();
   292         } else if (obj instanceof ScriptObjectMirror) {
   293             return ((ScriptObjectMirror)obj).isExtensible();
   294         } else {
   295             throw notAnObject(obj);
   296         }
   297     }
   299     /**
   300      * ECMA 15.2.3.14 Object.keys ( O )
   301      *
   302      * @param self self reference
   303      * @param obj  object from which to extract keys
   304      * @return array of keys in object
   305      */
   306     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   307     public static Object keys(final Object self, final Object obj) {
   308         if (obj instanceof ScriptObject) {
   309             final ScriptObject sobj = (ScriptObject)obj;
   310             return new NativeArray(sobj.getOwnKeys(false));
   311         } else if (obj instanceof ScriptObjectMirror) {
   312             final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
   313             return new NativeArray(sobjMirror.getOwnKeys(false));
   314         } else {
   315             throw notAnObject(obj);
   316         }
   317     }
   319     /**
   320      * ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value])
   321      *
   322      * Constructor
   323      *
   324      * @param newObj is the new object instantiated with the new operator
   325      * @param self   self reference
   326      * @param value  value of object to be instantiated
   327      * @return the new NativeObject
   328      */
   329     @Constructor
   330     public static Object construct(final boolean newObj, final Object self, final Object value) {
   331         final JSType type = JSType.of(value);
   333         // Object(null), Object(undefined), Object() are same as "new Object()"
   335         if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) {
   336             switch (type) {
   337             case BOOLEAN:
   338             case NUMBER:
   339             case STRING:
   340                 return Global.toObject(value);
   341             case OBJECT:
   342             case FUNCTION:
   343                 return value;
   344             case NULL:
   345             case UNDEFINED:
   346                 // fall through..
   347             default:
   348                 break;
   349             }
   351             return Global.newEmptyInstance();
   352         }
   354         return Global.toObject(value);
   355     }
   357     /**
   358      * ECMA 15.2.4.2 Object.prototype.toString ( )
   359      *
   360      * @param self self reference
   361      * @return ToString of object
   362      */
   363     @Function(attributes = Attribute.NOT_ENUMERABLE)
   364     public static Object toString(final Object self) {
   365         return ScriptRuntime.builtinObjectToString(self);
   366     }
   368     /**
   369      * ECMA 15.2.4.3 Object.prototype.toLocaleString ( )
   370      *
   371      * @param self self reference
   372      * @return localized ToString
   373      */
   374     @Function(attributes = Attribute.NOT_ENUMERABLE)
   375     public static Object toLocaleString(final Object self) {
   376         final Object obj = JSType.toScriptObject(self);
   377         if (obj instanceof ScriptObject) {
   378             final ScriptObject sobj = (ScriptObject)self;
   379             try {
   380                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   382                 if (toString instanceof ScriptFunction) {
   383                     return TO_STRING.getInvoker().invokeExact(toString, sobj);
   384                 }
   385             } catch (final RuntimeException | Error e) {
   386                 throw e;
   387             } catch (final Throwable t) {
   388                 throw new RuntimeException(t);
   389             }
   391             throw typeError("not.a.function", "toString");
   392         }
   394         return ScriptRuntime.builtinObjectToString(self);
   395     }
   397     /**
   398      * ECMA 15.2.4.4 Object.prototype.valueOf ( )
   399      *
   400      * @param self self reference
   401      * @return value of object
   402      */
   403     @Function(attributes = Attribute.NOT_ENUMERABLE)
   404     public static Object valueOf(final Object self) {
   405         return Global.toObject(self);
   406     }
   408     /**
   409      * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V)
   410      *
   411      * @param self self reference
   412      * @param v property to check for
   413      * @return true if property exists in object
   414      */
   415     @Function(attributes = Attribute.NOT_ENUMERABLE)
   416     public static Object hasOwnProperty(final Object self, final Object v) {
   417         final String str = JSType.toString(v);
   418         final Object obj = Global.toObject(self);
   420         return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str);
   421     }
   423     /**
   424      * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V)
   425      *
   426      * @param self self reference
   427      * @param v v prototype object to check against
   428      * @return true if object is prototype of v
   429      */
   430     @Function(attributes = Attribute.NOT_ENUMERABLE)
   431     public static Object isPrototypeOf(final Object self, final Object v) {
   432         if (!(v instanceof ScriptObject)) {
   433             return false;
   434         }
   436         final Object obj   = Global.toObject(self);
   437         ScriptObject proto = (ScriptObject)v;
   439         do {
   440             proto = proto.getProto();
   441             if (proto == obj) {
   442                 return true;
   443             }
   444         } while (proto != null);
   446         return false;
   447     }
   449     /**
   450      * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V)
   451      *
   452      * @param self self reference
   453      * @param v property to check if enumerable
   454      * @return true if property is enumerable
   455      */
   456     @Function(attributes = Attribute.NOT_ENUMERABLE)
   457     public static Object propertyIsEnumerable(final Object self, final Object v) {
   458         final String str = JSType.toString(v);
   459         final Object obj = Global.toObject(self);
   461         if (obj instanceof ScriptObject) {
   462             final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str);
   463             return property != null && property.isEnumerable();
   464         }
   466         return false;
   467     }
   468 }

mercurial