37 import java.util.function.Supplier; |
37 import java.util.function.Supplier; |
38 import jdk.dynalink.CallSiteDescriptor; |
38 import jdk.dynalink.CallSiteDescriptor; |
39 import jdk.dynalink.NamedOperation; |
39 import jdk.dynalink.NamedOperation; |
40 import jdk.dynalink.Operation; |
40 import jdk.dynalink.Operation; |
41 import jdk.dynalink.beans.BeansLinker; |
41 import jdk.dynalink.beans.BeansLinker; |
|
42 import jdk.dynalink.beans.StaticClass; |
42 import jdk.dynalink.linker.GuardedInvocation; |
43 import jdk.dynalink.linker.GuardedInvocation; |
43 import jdk.dynalink.linker.GuardingDynamicLinker; |
44 import jdk.dynalink.linker.GuardingDynamicLinker; |
44 import jdk.dynalink.linker.GuardingTypeConverterFactory; |
45 import jdk.dynalink.linker.GuardingTypeConverterFactory; |
45 import jdk.dynalink.linker.LinkRequest; |
46 import jdk.dynalink.linker.LinkRequest; |
46 import jdk.dynalink.linker.LinkerServices; |
47 import jdk.dynalink.linker.LinkerServices; |
|
48 import jdk.dynalink.linker.support.Guards; |
47 import jdk.dynalink.linker.support.Lookup; |
49 import jdk.dynalink.linker.support.Lookup; |
48 import jdk.nashorn.internal.codegen.types.Type; |
50 import jdk.nashorn.internal.codegen.types.Type; |
49 import jdk.nashorn.internal.runtime.ECMAException; |
51 import jdk.nashorn.internal.runtime.ECMAException; |
50 import jdk.nashorn.internal.runtime.JSType; |
52 import jdk.nashorn.internal.runtime.JSType; |
51 import jdk.nashorn.internal.runtime.ScriptRuntime; |
53 import jdk.nashorn.internal.runtime.ScriptRuntime; |
84 MH.asType(EMPTY_ELEM_GETTER, EMPTY_ELEM_GETTER.type().changeReturnType(void.class)); |
86 MH.asType(EMPTY_ELEM_GETTER, EMPTY_ELEM_GETTER.type().changeReturnType(void.class)); |
85 private static final MethodHandle EMPTY_ELEM_SETTER = |
87 private static final MethodHandle EMPTY_ELEM_SETTER = |
86 MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class); |
88 MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class); |
87 |
89 |
88 private static final MethodHandle THROW_STRICT_PROPERTY_SETTER; |
90 private static final MethodHandle THROW_STRICT_PROPERTY_SETTER; |
|
91 private static final MethodHandle THROW_STRICT_PROPERTY_REMOVER; |
89 private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED; |
92 private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED; |
|
93 private static final MethodHandle MISSING_PROPERTY_REMOVER; |
90 |
94 |
91 static { |
95 static { |
92 final Lookup lookup = new Lookup(MethodHandles.lookup()); |
96 final Lookup lookup = new Lookup(MethodHandles.lookup()); |
93 THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class); |
97 THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class); |
|
98 THROW_STRICT_PROPERTY_REMOVER = lookup.findOwnStatic("throwStrictPropertyRemover", boolean.class, Object.class, Object.class); |
94 THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class); |
99 THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class); |
|
100 MISSING_PROPERTY_REMOVER = lookup.findOwnStatic("missingPropertyRemover", boolean.class, Object.class, Object.class); |
95 } |
101 } |
96 |
102 |
97 private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception { |
103 private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception { |
98 final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); |
104 final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); |
99 final Object self = linkRequest.getReceiver(); |
105 final Object self = linkRequest.getReceiver(); |
122 } |
128 } |
123 |
129 |
124 static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { |
130 static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { |
125 final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); |
131 final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); |
126 final String operand = NashornCallSiteDescriptor.getOperand(desc); |
132 final String operand = NashornCallSiteDescriptor.getOperand(desc); |
|
133 final boolean strict = NashornCallSiteDescriptor.isStrict(desc); |
127 switch (NashornCallSiteDescriptor.getStandardOperation(desc)) { |
134 switch (NashornCallSiteDescriptor.getStandardOperation(desc)) { |
128 case GET: |
135 case GET: |
129 if (NashornCallSiteDescriptor.isOptimistic(desc)) { |
136 if (NashornCallSiteDescriptor.isOptimistic(desc)) { |
130 return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc); |
137 return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc); |
131 } else if (operand != null) { |
138 } else if (operand != null) { |
132 return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc); |
139 return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc); |
133 } |
140 } |
134 return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc); |
141 return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc); |
135 case SET: |
142 case SET: |
136 final boolean strict = NashornCallSiteDescriptor.isStrict(desc); |
|
137 if (strict) { |
143 if (strict) { |
138 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc); |
144 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc); |
139 } else if (operand != null) { |
145 } else if (operand != null) { |
140 return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc); |
146 return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc); |
141 } |
147 } |
142 return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc); |
148 return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc); |
|
149 case REMOVE: |
|
150 if (strict) { |
|
151 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_REMOVER, operand), desc); |
|
152 } |
|
153 return getInvocation(bindOperand(MISSING_PROPERTY_REMOVER, operand), linkerServices, desc); |
143 default: |
154 default: |
144 throw new AssertionError("unknown call type " + desc); |
155 throw new AssertionError("unknown call type " + desc); |
145 } |
156 } |
146 } |
157 } |
147 |
158 |
158 } |
169 } |
159 |
170 |
160 @SuppressWarnings("unused") |
171 @SuppressWarnings("unused") |
161 private static void throwStrictPropertySetter(final Object self, final Object name) { |
172 private static void throwStrictPropertySetter(final Object self, final Object name) { |
162 throw createTypeError(self, name, "cant.set.property"); |
173 throw createTypeError(self, name, "cant.set.property"); |
|
174 } |
|
175 |
|
176 @SuppressWarnings("unused") |
|
177 private static boolean throwStrictPropertyRemover(final Object self, final Object name) { |
|
178 if (isNonConfigurableProperty(self, name)) { |
|
179 throw createTypeError(self, name, "cant.delete.property"); |
|
180 } |
|
181 return true; |
|
182 } |
|
183 |
|
184 @SuppressWarnings("unused") |
|
185 private static boolean missingPropertyRemover(final Object self, final Object name) { |
|
186 return !isNonConfigurableProperty(self, name); |
|
187 } |
|
188 |
|
189 // Corresponds to ECMAScript 5.1 8.12.7 [[Delete]] point 3 check for "isConfigurable" (but negated) |
|
190 private static boolean isNonConfigurableProperty(final Object self, final Object name) { |
|
191 if (self instanceof StaticClass) { |
|
192 final Class<?> clazz = ((StaticClass)self).getRepresentedClass(); |
|
193 return BeansLinker.getReadableStaticPropertyNames(clazz).contains(name) || |
|
194 BeansLinker.getWritableStaticPropertyNames(clazz).contains(name) || |
|
195 BeansLinker.getStaticMethodNames(clazz).contains(name); |
|
196 } |
|
197 final Class<?> clazz = self.getClass(); |
|
198 return BeansLinker.getReadableInstancePropertyNames(clazz).contains(name) || |
|
199 BeansLinker.getWritableInstancePropertyNames(clazz).contains(name) || |
|
200 BeansLinker.getInstanceMethodNames(clazz).contains(name); |
163 } |
201 } |
164 |
202 |
165 private static ECMAException createTypeError(final Object self, final Object name, final String msg) { |
203 private static ECMAException createTypeError(final Object self, final Object name, final String msg) { |
166 return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self)); |
204 return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self)); |
167 } |
205 } |
213 throw typeError("not.a.function", "null"); |
251 throw typeError("not.a.function", "null"); |
214 case GET: |
252 case GET: |
215 throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null"); |
253 throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null"); |
216 case SET: |
254 case SET: |
217 throw typeError("cant.set.property", getArgument(linkRequest), "null"); |
255 throw typeError("cant.set.property", getArgument(linkRequest), "null"); |
|
256 case REMOVE: |
|
257 throw typeError("cant.delete.property", getArgument(linkRequest), "null"); |
218 default: |
258 default: |
219 throw new AssertionError("unknown call type " + desc); |
259 throw new AssertionError("unknown call type " + desc); |
220 } |
260 } |
221 } |
261 } |
222 |
262 |