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 */ 25 26 package jdk.nashorn.internal.runtime; 27 28 import static jdk.nashorn.internal.lookup.Lookup.MH; 29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 30 31 import java.lang.invoke.MethodHandle; 32 import java.lang.invoke.MethodHandles; 33 import java.util.ArrayList; 34 import jdk.nashorn.internal.objects.Global; 35 36 /** 37 * Instances of this class serve as "prototype" object for script functions. 38 * The purpose is to expose "constructor" property from "prototype". Also, nasgen 39 * generated prototype classes extend from this class. 40 */ 41 public class PrototypeObject extends ScriptObject { 42 private static final PropertyMap map$; 43 44 private Object constructor; 45 46 private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class); 47 private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class); 48 49 static { 50 final ArrayList<Property> properties = new ArrayList<>(1); 51 properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); 52 map$ = PropertyMap.newMap(properties); 53 } 54 PrototypeObject(final Global global, final PropertyMap map)55 private PrototypeObject(final Global global, final PropertyMap map) { 56 super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); 57 } 58 59 /** 60 * Prototype constructor 61 */ PrototypeObject()62 protected PrototypeObject() { 63 this(Global.instance(), map$); 64 } 65 66 /** 67 * PropertyObject constructor 68 * 69 * @param map property map 70 */ PrototypeObject(final PropertyMap map)71 protected PrototypeObject(final PropertyMap map) { 72 this(Global.instance(), map); 73 } 74 75 /** 76 * PropertyObject constructor 77 * 78 * @param func constructor function 79 */ PrototypeObject(final ScriptFunction func)80 protected PrototypeObject(final ScriptFunction func) { 81 this(Global.instance(), map$); 82 this.constructor = func; 83 } 84 85 /** 86 * Get the constructor for this {@code PrototypeObject} 87 * @param self self reference 88 * @return constructor, probably, but not necessarily, a {@link ScriptFunction} 89 */ getConstructor(final Object self)90 public static Object getConstructor(final Object self) { 91 return (self instanceof PrototypeObject) ? 92 ((PrototypeObject)self).getConstructor() : 93 UNDEFINED; 94 } 95 96 /** 97 * Reset the constructor for this {@code PrototypeObject} 98 * @param self self reference 99 * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction} 100 */ setConstructor(final Object self, final Object constructor)101 public static void setConstructor(final Object self, final Object constructor) { 102 if (self instanceof PrototypeObject) { 103 ((PrototypeObject)self).setConstructor(constructor); 104 } 105 } 106 getConstructor()107 private Object getConstructor() { 108 return constructor; 109 } 110 setConstructor(final Object constructor)111 private void setConstructor(final Object constructor) { 112 this.constructor = constructor; 113 } 114 findOwnMH(final String name, final Class<?> rtype, final Class<?>... types)115 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 116 return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types)); 117 } 118 } 119