25 |
25 |
26 package jdk.nashorn.internal.runtime.linker; |
26 package jdk.nashorn.internal.runtime.linker; |
27 |
27 |
28 import java.lang.invoke.MethodHandle; |
28 import java.lang.invoke.MethodHandle; |
29 import java.lang.invoke.MethodHandles; |
29 import java.lang.invoke.MethodHandles; |
30 import java.lang.invoke.MethodType; |
|
31 import java.util.HashMap; |
|
32 import java.util.Map; |
30 import java.util.Map; |
33 import javax.script.Bindings; |
31 import javax.script.Bindings; |
34 import jdk.internal.dynalink.CallSiteDescriptor; |
32 import jdk.internal.dynalink.CallSiteDescriptor; |
35 import jdk.internal.dynalink.linker.GuardedInvocation; |
33 import jdk.internal.dynalink.linker.GuardedInvocation; |
36 import jdk.internal.dynalink.linker.GuardedTypeConversion; |
|
37 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; |
|
38 import jdk.internal.dynalink.linker.LinkRequest; |
34 import jdk.internal.dynalink.linker.LinkRequest; |
39 import jdk.internal.dynalink.linker.LinkerServices; |
35 import jdk.internal.dynalink.linker.LinkerServices; |
40 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; |
36 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; |
41 import jdk.internal.dynalink.support.CallSiteDescriptorFactory; |
37 import jdk.internal.dynalink.support.CallSiteDescriptorFactory; |
42 import jdk.nashorn.api.scripting.JSObject; |
38 import jdk.nashorn.api.scripting.JSObject; |
47 |
43 |
48 /** |
44 /** |
49 * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well |
45 * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well |
50 * as ScriptObjects from other Nashorn contexts. |
46 * as ScriptObjects from other Nashorn contexts. |
51 */ |
47 */ |
52 final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory { |
48 final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { |
53 private final NashornBeansLinker nashornBeansLinker; |
49 private final NashornBeansLinker nashornBeansLinker; |
54 |
50 |
55 JSObjectLinker(final NashornBeansLinker nashornBeansLinker) { |
51 JSObjectLinker(final NashornBeansLinker nashornBeansLinker) { |
56 this.nashornBeansLinker = nashornBeansLinker; |
52 this.nashornBeansLinker = nashornBeansLinker; |
57 } |
53 } |
92 throw new AssertionError(); // Should never reach here. |
88 throw new AssertionError(); // Should never reach here. |
93 } |
89 } |
94 |
90 |
95 return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); |
91 return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); |
96 } |
92 } |
97 |
|
98 @Override |
|
99 public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { |
|
100 final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType); |
|
101 if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) { |
|
102 return null; |
|
103 } |
|
104 |
|
105 final MethodHandle converter = CONVERTERS.get(targetType); |
|
106 if(converter == null) { |
|
107 return null; |
|
108 } |
|
109 |
|
110 return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true); |
|
111 } |
|
112 |
|
113 |
93 |
114 private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { |
94 private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { |
115 final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); |
95 final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); |
116 final int c = desc.getNameTokenCount(); |
96 final int c = desc.getNameTokenCount(); |
117 |
97 |
206 } else if (key instanceof String || key instanceof ConsString) { |
186 } else if (key instanceof String || key instanceof ConsString) { |
207 ((JSObject)jsobj).setMember(key.toString(), value); |
187 ((JSObject)jsobj).setMember(key.toString(), value); |
208 } |
188 } |
209 } |
189 } |
210 |
190 |
211 @SuppressWarnings("unused") |
|
212 private static int toInt32(final JSObject obj) { |
|
213 return JSType.toInt32(toNumber(obj)); |
|
214 } |
|
215 |
|
216 @SuppressWarnings("unused") |
|
217 private static long toLong(final JSObject obj) { |
|
218 return JSType.toLong(toNumber(obj)); |
|
219 } |
|
220 |
|
221 private static double toNumber(final JSObject obj) { |
|
222 return obj == null ? 0 : obj.toNumber(); |
|
223 } |
|
224 |
|
225 @SuppressWarnings("unused") |
|
226 private static boolean toBoolean(final JSObject obj) { |
|
227 return obj != null; |
|
228 } |
|
229 |
|
230 private static int getIndex(final Number n) { |
191 private static int getIndex(final Number n) { |
231 final double value = n.doubleValue(); |
192 final double value = n.doubleValue(); |
232 return JSType.isRepresentableAsInt(value) ? (int)value : -1; |
193 return JSType.isRepresentableAsInt(value) ? (int)value : -1; |
233 } |
194 } |
234 |
195 |
259 private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class); |
220 private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class); |
260 private static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, Object.class, Object[].class); |
221 private static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, Object.class, Object[].class); |
261 private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class); |
222 private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class); |
262 private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class); |
223 private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class); |
263 |
224 |
264 private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>(); |
|
265 static { |
|
266 CONVERTERS.put(boolean.class, findOwnMH_S("toBoolean", boolean.class, JSObject.class)); |
|
267 CONVERTERS.put(int.class, findOwnMH_S("toInt32", int.class, JSObject.class)); |
|
268 CONVERTERS.put(long.class, findOwnMH_S("toLong", long.class, JSObject.class)); |
|
269 CONVERTERS.put(double.class, findOwnMH_S("toNumber", double.class, JSObject.class)); |
|
270 } |
|
271 |
|
272 private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) { |
225 private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) { |
273 return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types)); |
226 return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types)); |
274 } |
227 } |
275 |
228 |
276 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { |
229 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { |