author | attila |
Mon, 15 Jul 2013 12:33:48 +0200 | |
changeset 18876 | ada98218aaae |
parent 18860 | e387fde9322a |
child 18878 | 078eb52cf5bc |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 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.objects; |
|
27 |
||
28 |
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; |
|
29 |
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; |
|
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
30 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
31 |
import java.lang.invoke.MethodHandle; |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
32 |
import java.lang.invoke.MethodHandles; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
33 |
import java.lang.invoke.MethodType; |
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
34 |
import java.util.ArrayList; |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
35 |
import java.util.Collection; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
36 |
import java.util.HashSet; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
37 |
import java.util.List; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
38 |
import java.util.Set; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
39 |
import jdk.internal.dynalink.beans.BeansLinker; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
40 |
import jdk.internal.dynalink.beans.StaticClass; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
41 |
import jdk.internal.dynalink.linker.GuardedInvocation; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
42 |
import jdk.internal.dynalink.linker.GuardingDynamicLinker; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
43 |
import jdk.internal.dynalink.linker.LinkRequest; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
44 |
import jdk.internal.dynalink.support.CallSiteDescriptorFactory; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
45 |
import jdk.internal.dynalink.support.LinkRequestImpl; |
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
46 |
import jdk.nashorn.api.scripting.ScriptObjectMirror; |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
47 |
import jdk.nashorn.internal.lookup.Lookup; |
16147 | 48 |
import jdk.nashorn.internal.objects.annotations.Attribute; |
49 |
import jdk.nashorn.internal.objects.annotations.Constructor; |
|
50 |
import jdk.nashorn.internal.objects.annotations.Function; |
|
51 |
import jdk.nashorn.internal.objects.annotations.ScriptClass; |
|
52 |
import jdk.nashorn.internal.objects.annotations.Where; |
|
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
53 |
import jdk.nashorn.internal.runtime.AccessorProperty; |
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
54 |
import jdk.nashorn.internal.runtime.ECMAException; |
16147 | 55 |
import jdk.nashorn.internal.runtime.JSType; |
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
56 |
import jdk.nashorn.internal.runtime.Property; |
18618
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
18334
diff
changeset
|
57 |
import jdk.nashorn.internal.runtime.PropertyMap; |
16147 | 58 |
import jdk.nashorn.internal.runtime.ScriptFunction; |
59 |
import jdk.nashorn.internal.runtime.ScriptObject; |
|
60 |
import jdk.nashorn.internal.runtime.ScriptRuntime; |
|
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
61 |
import jdk.nashorn.internal.runtime.linker.Bootstrap; |
16147 | 62 |
import jdk.nashorn.internal.runtime.linker.InvokeByName; |
63 |
||
64 |
/** |
|
65 |
* ECMA 15.2 Object objects |
|
66 |
* |
|
67 |
* JavaScript Object constructor/prototype. Note: instances of this class are |
|
68 |
* never created. This class is not even a subclass of ScriptObject. But, we use |
|
69 |
* this class to generate prototype and constructor for "Object". |
|
70 |
* |
|
71 |
*/ |
|
72 |
@ScriptClass("Object") |
|
73 |
public final class NativeObject { |
|
74 |
private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); |
|
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
75 |
private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
76 |
private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class); |
16147 | 77 |
|
18618
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
18334
diff
changeset
|
78 |
// initialized by nasgen |
18842
3c3be808b593
8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
lagergren
parents:
18618
diff
changeset
|
79 |
@SuppressWarnings("unused") |
18618
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
18334
diff
changeset
|
80 |
private static PropertyMap $nasgenmap$; |
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
18334
diff
changeset
|
81 |
|
16147 | 82 |
private NativeObject() { |
18851
bdb92c95f886
8019947: inherited property invalidation does not work with two globals in same context
sundar
parents:
18842
diff
changeset
|
83 |
// don't create me! |
bdb92c95f886
8019947: inherited property invalidation does not work with two globals in same context
sundar
parents:
18842
diff
changeset
|
84 |
throw new UnsupportedOperationException(); |
16147 | 85 |
} |
86 |
||
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
87 |
private static ECMAException notAnObject(final Object obj) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
88 |
return typeError("not.an.object", ScriptRuntime.safeToString(obj)); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
89 |
} |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
90 |
|
16147 | 91 |
/** |
92 |
* ECMA 15.2.3.2 Object.getPrototypeOf ( O ) |
|
93 |
* |
|
94 |
* @param self self reference |
|
95 |
* @param obj object to get prototype from |
|
96 |
* @return the prototype of an object |
|
97 |
*/ |
|
98 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
99 |
public static Object getPrototypeOf(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
100 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
101 |
return ((ScriptObject)obj).getProto(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
102 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
103 |
return ((ScriptObjectMirror)obj).getProto(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
104 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
105 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
106 |
} |
16147 | 107 |
} |
108 |
||
109 |
/** |
|
110 |
* ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P ) |
|
111 |
* |
|
112 |
* @param self self reference |
|
113 |
* @param obj object from which to get property descriptor for {@code ToString(prop)} |
|
114 |
* @param prop property descriptor |
|
115 |
* @return property descriptor |
|
116 |
*/ |
|
117 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
118 |
public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
119 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
120 |
final String key = JSType.toString(prop); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
121 |
final ScriptObject sobj = (ScriptObject)obj; |
16147 | 122 |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
123 |
return sobj.getOwnPropertyDescriptor(key); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
124 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
125 |
final String key = JSType.toString(prop); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
126 |
final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj; |
16147 | 127 |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
128 |
return sobjMirror.getOwnPropertyDescriptor(key); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
129 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
130 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
131 |
} |
16147 | 132 |
} |
133 |
||
134 |
/** |
|
135 |
* ECMA 15.2.3.4 Object.getOwnPropertyNames ( O ) |
|
136 |
* |
|
137 |
* @param self self reference |
|
138 |
* @param obj object to query for property names |
|
139 |
* @return array of property names |
|
140 |
*/ |
|
141 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
142 |
public static Object getOwnPropertyNames(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
143 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
144 |
return new NativeArray(((ScriptObject)obj).getOwnKeys(true)); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
145 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
146 |
return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true)); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
147 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
148 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
149 |
} |
16147 | 150 |
} |
151 |
||
152 |
/** |
|
153 |
* ECMA 15.2.3.5 Object.create ( O [, Properties] ) |
|
154 |
* |
|
155 |
* @param self self reference |
|
156 |
* @param proto prototype object |
|
157 |
* @param props properties to define |
|
158 |
* @return object created |
|
159 |
*/ |
|
160 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
161 |
public static Object create(final Object self, final Object proto, final Object props) { |
|
162 |
if (proto != null) { |
|
163 |
Global.checkObject(proto); |
|
164 |
} |
|
165 |
||
166 |
// FIXME: should we create a proper object with correct number of |
|
167 |
// properties? |
|
168 |
final ScriptObject newObj = Global.newEmptyInstance(); |
|
169 |
newObj.setProtoCheck(proto); |
|
170 |
if (props != UNDEFINED) { |
|
171 |
NativeObject.defineProperties(self, newObj, props); |
|
172 |
} |
|
173 |
||
174 |
return newObj; |
|
175 |
} |
|
176 |
||
177 |
/** |
|
178 |
* ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes ) |
|
179 |
* |
|
180 |
* @param self self reference |
|
181 |
* @param obj object in which to define a property |
|
182 |
* @param prop property to define |
|
183 |
* @param attr attributes for property descriptor |
|
184 |
* @return object |
|
185 |
*/ |
|
186 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
187 |
public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) { |
|
188 |
Global.checkObject(obj); |
|
189 |
((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true); |
|
190 |
return obj; |
|
191 |
} |
|
192 |
||
193 |
/** |
|
194 |
* ECMA 5.2.3.7 Object.defineProperties ( O, Properties ) |
|
195 |
* |
|
196 |
* @param self self reference |
|
197 |
* @param obj object in which to define properties |
|
198 |
* @param props properties |
|
199 |
* @return object |
|
200 |
*/ |
|
201 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
202 |
public static Object defineProperties(final Object self, final Object obj, final Object props) { |
|
203 |
Global.checkObject(obj); |
|
204 |
||
205 |
final ScriptObject sobj = (ScriptObject)obj; |
|
206 |
final Object propsObj = Global.toObject(props); |
|
207 |
||
208 |
if (propsObj instanceof ScriptObject) { |
|
209 |
final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false); |
|
210 |
for (final Object key : keys) { |
|
211 |
final String prop = JSType.toString(key); |
|
212 |
sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true); |
|
213 |
} |
|
214 |
} |
|
215 |
return sobj; |
|
216 |
} |
|
217 |
||
218 |
/** |
|
219 |
* ECMA 15.2.3.8 Object.seal ( O ) |
|
220 |
* |
|
221 |
* @param self self reference |
|
222 |
* @param obj object to seal |
|
223 |
* @return sealed object |
|
224 |
*/ |
|
225 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
226 |
public static Object seal(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
227 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
228 |
return ((ScriptObject)obj).seal(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
229 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
230 |
return ((ScriptObjectMirror)obj).seal(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
231 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
232 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
233 |
} |
16147 | 234 |
} |
235 |
||
236 |
||
237 |
/** |
|
238 |
* ECMA 15.2.3.9 Object.freeze ( O ) |
|
239 |
* |
|
240 |
* @param self self reference |
|
241 |
* @param obj object to freeze |
|
242 |
* @return frozen object |
|
243 |
*/ |
|
244 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
245 |
public static Object freeze(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
246 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
247 |
return ((ScriptObject)obj).freeze(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
248 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
249 |
return ((ScriptObjectMirror)obj).freeze(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
250 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
251 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
252 |
} |
16147 | 253 |
} |
254 |
||
255 |
/** |
|
256 |
* ECMA 15.2.3.10 Object.preventExtensions ( O ) |
|
257 |
* |
|
258 |
* @param self self reference |
|
259 |
* @param obj object, for which to set the internal extensible property to false |
|
260 |
* @return object |
|
261 |
*/ |
|
262 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
263 |
public static Object preventExtensions(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
264 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
265 |
return ((ScriptObject)obj).preventExtensions(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
266 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
267 |
return ((ScriptObjectMirror)obj).preventExtensions(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
268 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
269 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
270 |
} |
16147 | 271 |
} |
272 |
||
273 |
/** |
|
274 |
* ECMA 15.2.3.11 Object.isSealed ( O ) |
|
275 |
* |
|
276 |
* @param self self reference |
|
277 |
* @param obj check whether an object is sealed |
|
278 |
* @return true if sealed, false otherwise |
|
279 |
*/ |
|
280 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
281 |
public static Object isSealed(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
282 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
283 |
return ((ScriptObject)obj).isSealed(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
284 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
285 |
return ((ScriptObjectMirror)obj).isSealed(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
286 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
287 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
288 |
} |
16147 | 289 |
} |
290 |
||
291 |
/** |
|
292 |
* ECMA 15.2.3.12 Object.isFrozen ( O ) |
|
293 |
* |
|
294 |
* @param self self reference |
|
295 |
* @param obj check whether an object |
|
296 |
* @return true if object is frozen, false otherwise |
|
297 |
*/ |
|
298 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
299 |
public static Object isFrozen(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
300 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
301 |
return ((ScriptObject)obj).isFrozen(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
302 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
303 |
return ((ScriptObjectMirror)obj).isFrozen(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
304 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
305 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
306 |
} |
16147 | 307 |
} |
308 |
||
309 |
/** |
|
310 |
* ECMA 15.2.3.13 Object.isExtensible ( O ) |
|
311 |
* |
|
312 |
* @param self self reference |
|
313 |
* @param obj check whether an object is extensible |
|
314 |
* @return true if object is extensible, false otherwise |
|
315 |
*/ |
|
316 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
317 |
public static Object isExtensible(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
318 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
319 |
return ((ScriptObject)obj).isExtensible(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
320 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
321 |
return ((ScriptObjectMirror)obj).isExtensible(); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
322 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
323 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
324 |
} |
16147 | 325 |
} |
326 |
||
327 |
/** |
|
328 |
* ECMA 15.2.3.14 Object.keys ( O ) |
|
329 |
* |
|
330 |
* @param self self reference |
|
331 |
* @param obj object from which to extract keys |
|
332 |
* @return array of keys in object |
|
333 |
*/ |
|
334 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
|
335 |
public static Object keys(final Object self, final Object obj) { |
|
18334
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
336 |
if (obj instanceof ScriptObject) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
337 |
final ScriptObject sobj = (ScriptObject)obj; |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
338 |
return new NativeArray(sobj.getOwnKeys(false)); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
339 |
} else if (obj instanceof ScriptObjectMirror) { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
340 |
final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj; |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
341 |
return new NativeArray(sobjMirror.getOwnKeys(false)); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
342 |
} else { |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
343 |
throw notAnObject(obj); |
47413e8d71b5
8016618: script mirror object access should be improved
sundar
parents:
16256
diff
changeset
|
344 |
} |
16147 | 345 |
} |
346 |
||
347 |
/** |
|
348 |
* ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value]) |
|
349 |
* |
|
350 |
* Constructor |
|
351 |
* |
|
352 |
* @param newObj is the new object instantiated with the new operator |
|
353 |
* @param self self reference |
|
354 |
* @param value value of object to be instantiated |
|
355 |
* @return the new NativeObject |
|
356 |
*/ |
|
357 |
@Constructor |
|
358 |
public static Object construct(final boolean newObj, final Object self, final Object value) { |
|
359 |
final JSType type = JSType.of(value); |
|
360 |
||
361 |
// Object(null), Object(undefined), Object() are same as "new Object()" |
|
362 |
||
363 |
if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) { |
|
364 |
switch (type) { |
|
365 |
case BOOLEAN: |
|
366 |
case NUMBER: |
|
367 |
case STRING: |
|
368 |
return Global.toObject(value); |
|
369 |
case OBJECT: |
|
370 |
case FUNCTION: |
|
371 |
return value; |
|
372 |
case NULL: |
|
373 |
case UNDEFINED: |
|
374 |
// fall through.. |
|
375 |
default: |
|
376 |
break; |
|
377 |
} |
|
378 |
||
379 |
return Global.newEmptyInstance(); |
|
380 |
} |
|
381 |
||
382 |
return Global.toObject(value); |
|
383 |
} |
|
384 |
||
385 |
/** |
|
386 |
* ECMA 15.2.4.2 Object.prototype.toString ( ) |
|
387 |
* |
|
388 |
* @param self self reference |
|
389 |
* @return ToString of object |
|
390 |
*/ |
|
391 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
392 |
public static Object toString(final Object self) { |
|
393 |
return ScriptRuntime.builtinObjectToString(self); |
|
394 |
} |
|
395 |
||
396 |
/** |
|
397 |
* ECMA 15.2.4.3 Object.prototype.toLocaleString ( ) |
|
398 |
* |
|
399 |
* @param self self reference |
|
400 |
* @return localized ToString |
|
401 |
*/ |
|
402 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
403 |
public static Object toLocaleString(final Object self) { |
|
16188 | 404 |
final Object obj = JSType.toScriptObject(self); |
16147 | 405 |
if (obj instanceof ScriptObject) { |
406 |
final ScriptObject sobj = (ScriptObject)self; |
|
407 |
try { |
|
408 |
final Object toString = TO_STRING.getGetter().invokeExact(sobj); |
|
409 |
||
410 |
if (toString instanceof ScriptFunction) { |
|
411 |
return TO_STRING.getInvoker().invokeExact(toString, sobj); |
|
412 |
} |
|
413 |
} catch (final RuntimeException | Error e) { |
|
414 |
throw e; |
|
415 |
} catch (final Throwable t) { |
|
416 |
throw new RuntimeException(t); |
|
417 |
} |
|
418 |
||
16256
f2d9a0c49914
8007002: Replace implicit exception throwing methods with explicit throws - simplify control flow and remove useless code
lagergren
parents:
16188
diff
changeset
|
419 |
throw typeError("not.a.function", "toString"); |
16147 | 420 |
} |
421 |
||
422 |
return ScriptRuntime.builtinObjectToString(self); |
|
423 |
} |
|
424 |
||
425 |
/** |
|
426 |
* ECMA 15.2.4.4 Object.prototype.valueOf ( ) |
|
427 |
* |
|
428 |
* @param self self reference |
|
429 |
* @return value of object |
|
430 |
*/ |
|
431 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
432 |
public static Object valueOf(final Object self) { |
|
433 |
return Global.toObject(self); |
|
434 |
} |
|
435 |
||
436 |
/** |
|
437 |
* ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V) |
|
438 |
* |
|
439 |
* @param self self reference |
|
440 |
* @param v property to check for |
|
441 |
* @return true if property exists in object |
|
442 |
*/ |
|
443 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
444 |
public static Object hasOwnProperty(final Object self, final Object v) { |
|
445 |
final String str = JSType.toString(v); |
|
446 |
final Object obj = Global.toObject(self); |
|
447 |
||
448 |
return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str); |
|
449 |
} |
|
450 |
||
451 |
/** |
|
452 |
* ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V) |
|
453 |
* |
|
454 |
* @param self self reference |
|
455 |
* @param v v prototype object to check against |
|
456 |
* @return true if object is prototype of v |
|
457 |
*/ |
|
458 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
459 |
public static Object isPrototypeOf(final Object self, final Object v) { |
|
460 |
if (!(v instanceof ScriptObject)) { |
|
461 |
return false; |
|
462 |
} |
|
463 |
||
464 |
final Object obj = Global.toObject(self); |
|
465 |
ScriptObject proto = (ScriptObject)v; |
|
466 |
||
467 |
do { |
|
468 |
proto = proto.getProto(); |
|
469 |
if (proto == obj) { |
|
470 |
return true; |
|
471 |
} |
|
472 |
} while (proto != null); |
|
473 |
||
474 |
return false; |
|
475 |
} |
|
476 |
||
477 |
/** |
|
478 |
* ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V) |
|
479 |
* |
|
480 |
* @param self self reference |
|
481 |
* @param v property to check if enumerable |
|
482 |
* @return true if property is enumerable |
|
483 |
*/ |
|
484 |
@Function(attributes = Attribute.NOT_ENUMERABLE) |
|
485 |
public static Object propertyIsEnumerable(final Object self, final Object v) { |
|
486 |
final String str = JSType.toString(v); |
|
487 |
final Object obj = Global.toObject(self); |
|
488 |
||
489 |
if (obj instanceof ScriptObject) { |
|
490 |
final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str); |
|
491 |
return property != null && property.isEnumerable(); |
|
492 |
} |
|
493 |
||
494 |
return false; |
|
495 |
} |
|
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
496 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
497 |
/** |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
498 |
* Nashorn extension: Object.bindProperties |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
499 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
500 |
* Binds the source object's properties to the target object. Binding |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
501 |
* properties allows two-way read/write for the properties of the source object. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
502 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
503 |
* Example: |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
504 |
* <pre> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
505 |
* var obj = { x: 34, y: 100 }; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
506 |
* var foo = {} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
507 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
508 |
* // bind properties of "obj" to "foo" object |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
509 |
* Object.bindProperties(foo, obj); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
510 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
511 |
* // now, we can access/write on 'foo' properties |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
512 |
* print(foo.x); // prints obj.x which is 34 |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
513 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
514 |
* // update obj.x via foo.x |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
515 |
* foo.x = "hello"; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
516 |
* print(obj.x); // prints "hello" now |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
517 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
518 |
* obj.x = 42; // foo.x also becomes 42 |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
519 |
* print(foo.x); // prints 42 |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
520 |
* </pre> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
521 |
* <p> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
522 |
* The source object bound can be a ScriptObject or a ScriptOjectMirror. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
523 |
* null or undefined source object results in TypeError being thrown. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
524 |
* </p> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
525 |
* Example: |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
526 |
* <pre> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
527 |
* var obj = loadWithNewGlobal({ |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
528 |
* name: "test", |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
529 |
* script: "obj = { x: 33, y: 'hello' }" |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
530 |
* }); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
531 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
532 |
* // bind 'obj's properties to global scope 'this' |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
533 |
* Object.bindProperties(this, obj); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
534 |
* print(x); // prints 33 |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
535 |
* print(y); // prints "hello" |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
536 |
* x = Math.PI; // changes obj.x to Math.PI |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
537 |
* print(obj.x); // prints Math.PI |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
538 |
* </pre> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
539 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
540 |
* Limitations of property binding: |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
541 |
* <ul> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
542 |
* <li> Only enumerable, immediate (not proto inherited) properties of the source object are bound. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
543 |
* <li> If the target object already contains a property called "foo", the source's "foo" is skipped (not bound). |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
544 |
* <li> Properties added to the source object after binding to the target are not bound. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
545 |
* <li> Property configuration changes on the source object (or on the target) is not propagated. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
546 |
* <li> Delete of property on the target (or the source) is not propagated - |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
547 |
* only the property value is set to 'undefined' if the property happens to be a data property. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
548 |
* </ul> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
549 |
* <p> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
550 |
* It is recommended that the bound properties be treated as non-configurable |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
551 |
* properties to avoid surprises. |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
552 |
* </p> |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
553 |
* |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
554 |
* @param self self reference |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
555 |
* @param target the target object to which the source object's properties are bound |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
556 |
* @param source the source object whose properties are bound to the target |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
557 |
* @return the target object after property binding |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
558 |
*/ |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
559 |
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
560 |
public static Object bindProperties(final Object self, final Object target, final Object source) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
561 |
// target object has to be a ScriptObject |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
562 |
Global.checkObject(target); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
563 |
// check null or undefined source object |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
564 |
Global.checkObjectCoercible(source); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
565 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
566 |
final ScriptObject targetObj = (ScriptObject)target; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
567 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
568 |
if (source instanceof ScriptObject) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
569 |
final ScriptObject sourceObj = (ScriptObject)source; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
570 |
final Property[] properties = sourceObj.getMap().getProperties(); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
571 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
572 |
// filter non-enumerable properties |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
573 |
final ArrayList<Property> propList = new ArrayList<>(); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
574 |
for (Property prop : properties) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
575 |
if (prop.isEnumerable()) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
576 |
propList.add(prop); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
577 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
578 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
579 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
580 |
if (! propList.isEmpty()) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
581 |
targetObj.addBoundProperties(sourceObj, propList.toArray(new Property[propList.size()])); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
582 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
583 |
} else if (source instanceof ScriptObjectMirror) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
584 |
// get enumerable, immediate properties of mirror |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
585 |
final ScriptObjectMirror mirror = (ScriptObjectMirror)source; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
586 |
final String[] keys = mirror.getOwnKeys(false); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
587 |
if (keys.length == 0) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
588 |
// nothing to bind |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
589 |
return target; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
590 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
591 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
592 |
// make accessor properties using dynamic invoker getters and setters |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
593 |
final AccessorProperty[] props = new AccessorProperty[keys.length]; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
594 |
for (int idx = 0; idx < keys.length; idx++) { |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
595 |
final String name = keys[idx]; |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
596 |
final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
597 |
final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE); |
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
598 |
props[idx] = (AccessorProperty.create(name, 0, getter, setter)); |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
599 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
600 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
601 |
targetObj.addBoundProperties(source, props); |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
602 |
} else if (source instanceof StaticClass) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
603 |
final Class<?> clazz = ((StaticClass)source).getRepresentedClass(); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
604 |
bindBeanProperties(targetObj, source, BeansLinker.getReadableStaticPropertyNames(clazz), |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
605 |
BeansLinker.getWritableStaticPropertyNames(clazz), BeansLinker.getStaticMethodNames(clazz)); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
606 |
} else { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
607 |
final Class<?> clazz = source.getClass(); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
608 |
bindBeanProperties(targetObj, source, BeansLinker.getReadableInstancePropertyNames(clazz), |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
609 |
BeansLinker.getWritableInstancePropertyNames(clazz), BeansLinker.getInstanceMethodNames(clazz)); |
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
610 |
} |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
611 |
|
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
612 |
return target; |
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18851
diff
changeset
|
613 |
} |
18876
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
614 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
615 |
private static void bindBeanProperties(final ScriptObject targetObj, final Object source, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
616 |
final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
617 |
final Collection<String> methodNames) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
618 |
final Set<String> propertyNames = new HashSet<>(readablePropertyNames); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
619 |
propertyNames.addAll(writablePropertyNames); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
620 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
621 |
final Class<?> clazz = source.getClass(); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
622 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
623 |
final MethodType getterType = MethodType.methodType(Object.class, clazz); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
624 |
final MethodType setterType = MethodType.methodType(Object.class, clazz, Object.class); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
625 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
626 |
final GuardingDynamicLinker linker = BeansLinker.getLinkerForClass(clazz); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
627 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
628 |
final List<AccessorProperty> properties = new ArrayList<>(propertyNames.size() + methodNames.size()); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
629 |
for(final String methodName: methodNames) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
630 |
properties.add(AccessorProperty.create(methodName, Property.NOT_WRITABLE, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
631 |
getBoundBeanMethodGetter(source, getBeanOperation(linker, "dyn:getMethod:" + methodName, getterType, source)), |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
632 |
null)); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
633 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
634 |
for(final String propertyName: propertyNames) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
635 |
final boolean isWritable = writablePropertyNames.contains(propertyName); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
636 |
properties.add(AccessorProperty.create(propertyName, isWritable ? 0 : Property.NOT_WRITABLE, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
637 |
readablePropertyNames.contains(propertyName) ? getBeanOperation(linker, "dyn:getProp:" + propertyName, getterType, source) : Lookup.EMPTY_GETTER, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
638 |
isWritable ? getBeanOperation(linker, "dyn:setProp:" + propertyName, setterType, source) : Lookup.EMPTY_SETTER)); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
639 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
640 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
641 |
targetObj.addBoundProperties(source, properties.toArray(new AccessorProperty[properties.size()])); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
642 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
643 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
644 |
private static MethodHandle getBoundBeanMethodGetter(Object source, MethodHandle methodGetter) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
645 |
try { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
646 |
// NOTE: we're relying on the fact that "dyn:getMethod:..." return value is constant for any given method |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
647 |
// name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
648 |
// constant for any given method name and object's class.) |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
649 |
return MethodHandles.dropArguments(MethodHandles.constant(Object.class, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
650 |
Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
651 |
} catch(RuntimeException|Error e) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
652 |
throw e; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
653 |
} catch(Throwable t) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
654 |
throw new RuntimeException(t); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
655 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
656 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
657 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
658 |
private static MethodHandle getBeanOperation(final GuardingDynamicLinker linker, final String operation, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
659 |
final MethodType methodType, final Object source) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
660 |
final GuardedInvocation inv; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
661 |
try { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
662 |
inv = linker.getGuardedInvocation(createLinkRequest(operation, methodType, source), |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
663 |
Bootstrap.getLinkerServices()); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
664 |
assert passesGuard(source, inv.getGuard()); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
665 |
} catch(RuntimeException|Error e) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
666 |
throw e; |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
667 |
} catch(Throwable t) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
668 |
throw new RuntimeException(t); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
669 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
670 |
assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints. |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
671 |
// We discard the guard, as all method handles will be bound to a specific object. |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
672 |
return inv.getInvocation(); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
673 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
674 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
675 |
private static boolean passesGuard(final Object obj, final MethodHandle guard) throws Throwable { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
676 |
return guard == null || (boolean)guard.invoke(obj); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
677 |
} |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
678 |
|
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
679 |
private static LinkRequest createLinkRequest(String operation, MethodType methodType, Object source) { |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
680 |
return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation, |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
681 |
methodType), false, source); |
ada98218aaae
8020324: Implement Object.bindProperties(target, source) for beans
attila
parents:
18860
diff
changeset
|
682 |
} |
16147 | 683 |
} |