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

Tue, 22 Jan 2013 22:07:12 +0530

author
sundar
date
Tue, 22 Jan 2013 22:07:12 +0530
changeset 44
e62dba3ce52b
parent 7
5a1b0714df0e
child 112
267cc4c85160
permissions
-rw-r--r--

8006678: Avoid too many Context.getGlobal() calls
Reviewed-by: lagergren, jlaskey

     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.internal.objects.annotations.Attribute;
    32 import jdk.nashorn.internal.objects.annotations.Constructor;
    33 import jdk.nashorn.internal.objects.annotations.Function;
    34 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    35 import jdk.nashorn.internal.objects.annotations.Where;
    36 import jdk.nashorn.internal.runtime.JSType;
    37 import jdk.nashorn.internal.runtime.ScriptFunction;
    38 import jdk.nashorn.internal.runtime.ScriptObject;
    39 import jdk.nashorn.internal.runtime.ScriptRuntime;
    40 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    42 /**
    43  * ECMA 15.2 Object objects
    44  *
    45  * JavaScript Object constructor/prototype. Note: instances of this class are
    46  * never created. This class is not even a subclass of ScriptObject. But, we use
    47  * this class to generate prototype and constructor for "Object".
    48  *
    49  */
    50 @ScriptClass("Object")
    51 public final class NativeObject {
    52     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    54     private NativeObject() {
    55     }
    57     /**
    58      * ECMA 15.2.3.2 Object.getPrototypeOf ( O )
    59      *
    60      * @param  self self reference
    61      * @param  obj object to get prototype from
    62      * @return the prototype of an object
    63      */
    64     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    65     public static Object getPrototypeOf(final Object self, final Object obj) {
    66         Global.checkObject(obj);
    68         return ((ScriptObject)obj).getProto();
    69     }
    71     /**
    72      * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
    73      *
    74      * @param self  self reference
    75      * @param obj   object from which to get property descriptor for {@code ToString(prop)}
    76      * @param prop  property descriptor
    77      * @return property descriptor
    78      */
    79     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    80     public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
    81         Global.checkObject(obj);
    83         final String       key  = JSType.toString(prop);
    84         final ScriptObject sobj = (ScriptObject)obj;
    86         return sobj.getOwnPropertyDescriptor(key);
    87     }
    89     /**
    90      * ECMA 15.2.3.4 Object.getOwnPropertyNames ( O )
    91      *
    92      * @param self self reference
    93      * @param obj  object to query for property names
    94      * @return array of property names
    95      */
    96     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    97     public static Object getOwnPropertyNames(final Object self, final Object obj) {
    98         Global.checkObject(obj);
   100         return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
   101     }
   103     /**
   104      * ECMA 15.2.3.5 Object.create ( O [, Properties] )
   105      *
   106      * @param self  self reference
   107      * @param proto prototype object
   108      * @param props properties to define
   109      * @return object created
   110      */
   111     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   112     public static Object create(final Object self, final Object proto, final Object props) {
   113         if (proto != null) {
   114             Global.checkObject(proto);
   115         }
   117         // FIXME: should we create a proper object with correct number of
   118         // properties?
   119         final ScriptObject newObj = Global.newEmptyInstance();
   120         newObj.setProtoCheck(proto);
   121         if (props != UNDEFINED) {
   122             NativeObject.defineProperties(self, newObj, props);
   123         }
   125         return newObj;
   126     }
   128     /**
   129      * ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes )
   130      *
   131      * @param self self reference
   132      * @param obj  object in which to define a property
   133      * @param prop property to define
   134      * @param attr attributes for property descriptor
   135      * @return object
   136      */
   137     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   138     public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
   139         Global.checkObject(obj);
   140         ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true);
   141         return obj;
   142     }
   144     /**
   145      * ECMA 5.2.3.7 Object.defineProperties ( O, Properties )
   146      *
   147      * @param self  self reference
   148      * @param obj   object in which to define properties
   149      * @param props properties
   150      * @return object
   151      */
   152     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   153     public static Object defineProperties(final Object self, final Object obj, final Object props) {
   154         Global.checkObject(obj);
   156         final ScriptObject sobj     = (ScriptObject)obj;
   157         final Object       propsObj = Global.toObject(props);
   159         if (propsObj instanceof ScriptObject) {
   160             final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false);
   161             for (final Object key : keys) {
   162                 final String prop = JSType.toString(key);
   163                 sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true);
   164             }
   165         }
   166         return sobj;
   167     }
   169     /**
   170      * ECMA 15.2.3.8 Object.seal ( O )
   171      *
   172      * @param self self reference
   173      * @param obj  object to seal
   174      * @return sealed object
   175      */
   176     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   177     public static Object seal(final Object self, final Object obj) {
   178         Global.checkObject(obj);
   179         return ((ScriptObject)obj).seal();
   180     }
   183     /**
   184      * ECMA 15.2.3.9 Object.freeze ( O )
   185      *
   186      * @param self self reference
   187      * @param obj object to freeze
   188      * @return frozen object
   189      */
   190     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   191     public static Object freeze(final Object self, final Object obj) {
   192         Global.checkObject(obj);
   193         return ((ScriptObject)obj).freeze();
   194     }
   196     /**
   197      * ECMA 15.2.3.10 Object.preventExtensions ( O )
   198      *
   199      * @param self self reference
   200      * @param obj  object, for which to set the internal extensible property to false
   201      * @return object
   202      */
   203     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   204     public static Object preventExtensions(final Object self, final Object obj) {
   205         Global.checkObject(obj);
   206         return ((ScriptObject)obj).preventExtensions();
   207     }
   209     /**
   210      * ECMA 15.2.3.11 Object.isSealed ( O )
   211      *
   212      * @param self self reference
   213      * @param obj check whether an object is sealed
   214      * @return true if sealed, false otherwise
   215      */
   216     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   217     public static Object isSealed(final Object self, final Object obj) {
   218         Global.checkObject(obj);
   219         return ((ScriptObject)obj).isSealed();
   220     }
   222     /**
   223      * ECMA 15.2.3.12 Object.isFrozen ( O )
   224      *
   225      * @param self self reference
   226      * @param obj check whether an object
   227      * @return true if object is frozen, false otherwise
   228      */
   229     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   230     public static Object isFrozen(final Object self, final Object obj) {
   231         Global.checkObject(obj);
   232         return ((ScriptObject)obj).isFrozen();
   233     }
   235     /**
   236      * ECMA 15.2.3.13 Object.isExtensible ( O )
   237      *
   238      * @param self self reference
   239      * @param obj check whether an object is extensible
   240      * @return true if object is extensible, false otherwise
   241      */
   242     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   243     public static Object isExtensible(final Object self, final Object obj) {
   244         Global.checkObject(obj);
   245         return ((ScriptObject)obj).isExtensible();
   246     }
   248     /**
   249      * ECMA 15.2.3.14 Object.keys ( O )
   250      *
   251      * @param self self reference
   252      * @param obj  object from which to extract keys
   253      * @return array of keys in object
   254      */
   255     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   256     public static Object keys(final Object self, final Object obj) {
   257         Global.checkObject(obj);
   258         final ScriptObject sobj = (ScriptObject)obj;
   259         return new NativeArray(sobj.getOwnKeys(false));
   260     }
   262     /**
   263      * ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value])
   264      *
   265      * Constructor
   266      *
   267      * @param newObj is the new object instantiated with the new operator
   268      * @param self   self reference
   269      * @param value  value of object to be instantiated
   270      * @return the new NativeObject
   271      */
   272     @Constructor
   273     public static Object construct(final boolean newObj, final Object self, final Object value) {
   274         final JSType type = JSType.of(value);
   276         // Object(null), Object(undefined), Object() are same as "new Object()"
   278         if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) {
   279             switch (type) {
   280             case BOOLEAN:
   281             case NUMBER:
   282             case STRING:
   283                 return Global.toObject(value);
   284             case OBJECT:
   285             case FUNCTION:
   286                 return value;
   287             case NULL:
   288             case UNDEFINED:
   289                 // fall through..
   290             default:
   291                 break;
   292             }
   294             return Global.newEmptyInstance();
   295         }
   297         return Global.toObject(value);
   298     }
   300     /**
   301      * ECMA 15.2.4.2 Object.prototype.toString ( )
   302      *
   303      * @param self self reference
   304      * @return ToString of object
   305      */
   306     @Function(attributes = Attribute.NOT_ENUMERABLE)
   307     public static Object toString(final Object self) {
   308         return ScriptRuntime.builtinObjectToString(self);
   309     }
   311     /**
   312      * ECMA 15.2.4.3 Object.prototype.toLocaleString ( )
   313      *
   314      * @param self self reference
   315      * @return localized ToString
   316      */
   317     @Function(attributes = Attribute.NOT_ENUMERABLE)
   318     public static Object toLocaleString(final Object self) {
   319         final Object obj = JSType.toScriptObject(self);
   320         if (obj instanceof ScriptObject) {
   321             final ScriptObject sobj = (ScriptObject)self;
   322             try {
   323                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   325                 if (toString instanceof ScriptFunction) {
   326                     return TO_STRING.getInvoker().invokeExact(toString, sobj);
   327                 }
   328             } catch (final RuntimeException | Error e) {
   329                 throw e;
   330             } catch (final Throwable t) {
   331                 throw new RuntimeException(t);
   332             }
   334             typeError("not.a.function", "toString");
   335             throw new AssertionError(); // never reached
   336         }
   338         return ScriptRuntime.builtinObjectToString(self);
   339     }
   341     /**
   342      * ECMA 15.2.4.4 Object.prototype.valueOf ( )
   343      *
   344      * @param self self reference
   345      * @return value of object
   346      */
   347     @Function(attributes = Attribute.NOT_ENUMERABLE)
   348     public static Object valueOf(final Object self) {
   349         return Global.toObject(self);
   350     }
   352     /**
   353      * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V)
   354      *
   355      * @param self self reference
   356      * @param v property to check for
   357      * @return true if property exists in object
   358      */
   359     @Function(attributes = Attribute.NOT_ENUMERABLE)
   360     public static Object hasOwnProperty(final Object self, final Object v) {
   361         final String str = JSType.toString(v);
   362         final Object obj = Global.toObject(self);
   364         return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str);
   365     }
   367     /**
   368      * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V)
   369      *
   370      * @param self self reference
   371      * @param v v prototype object to check against
   372      * @return true if object is prototype of v
   373      */
   374     @Function(attributes = Attribute.NOT_ENUMERABLE)
   375     public static Object isPrototypeOf(final Object self, final Object v) {
   376         if (!(v instanceof ScriptObject)) {
   377             return false;
   378         }
   380         final Object obj   = Global.toObject(self);
   381         ScriptObject proto = (ScriptObject)v;
   383         do {
   384             proto = proto.getProto();
   385             if (proto == obj) {
   386                 return true;
   387             }
   388         } while (proto != null);
   390         return false;
   391     }
   393     /**
   394      * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V)
   395      *
   396      * @param self self reference
   397      * @param v property to check if enumerable
   398      * @return true if property is enumerable
   399      */
   400     @Function(attributes = Attribute.NOT_ENUMERABLE)
   401     public static Object propertyIsEnumerable(final Object self, final Object v) {
   402         final String str = JSType.toString(v);
   403         final Object obj = Global.toObject(self);
   405         if (obj instanceof ScriptObject) {
   406             final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str);
   407             return property != null && property.isEnumerable();
   408         }
   410         return false;
   411     }
   412 }

mercurial