Wed, 03 Jun 2015 16:44:24 +0200
8081813: JSONListAdapter should delegate its [[DefaultValue]] to wrapped object
Reviewed-by: lagergren, sundar
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.api.scripting;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Set;
31 import jdk.nashorn.internal.runtime.JSONListAdapter;
32 import jdk.nashorn.internal.runtime.JSType;
34 /**
35 * This is the base class for nashorn ScriptObjectMirror class.
36 *
37 * This class can also be subclassed by an arbitrary Java class. Nashorn will
38 * treat objects of such classes just like nashorn script objects. Usual nashorn
39 * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
40 * to appropriate method call of this class.
41 *
42 * @since 1.8u40
43 */
44 @jdk.Exported
45 public abstract class AbstractJSObject implements JSObject {
46 /**
47 * Call this object as a JavaScript function. This is equivalent to
48 * 'func.apply(thiz, args)' in JavaScript.
49 *
50 * @param thiz 'this' object to be passed to the function
51 * @param args arguments to method
52 * @return result of call
53 */
54 @Override
55 public Object call(final Object thiz, final Object... args) {
56 throw new UnsupportedOperationException("call");
57 }
59 /**
60 * Call this 'constructor' JavaScript function to create a new object.
61 * This is equivalent to 'new func(arg1, arg2...)' in JavaScript.
62 *
63 * @param args arguments to method
64 * @return result of constructor call
65 */
66 @Override
67 public Object newObject(final Object... args) {
68 throw new UnsupportedOperationException("newObject");
69 }
71 /**
72 * Evaluate a JavaScript expression.
73 *
74 * @param s JavaScript expression to evaluate
75 * @return evaluation result
76 */
77 @Override
78 public Object eval(final String s) {
79 throw new UnsupportedOperationException("eval");
80 }
82 /**
83 * Retrieves a named member of this JavaScript object.
84 *
85 * @param name of member
86 * @return member
87 */
88 @Override
89 public Object getMember(final String name) {
90 return null;
91 }
93 /**
94 * Retrieves an indexed member of this JavaScript object.
95 *
96 * @param index index slot to retrieve
97 * @return member
98 */
99 @Override
100 public Object getSlot(final int index) {
101 return null;
102 }
104 /**
105 * Does this object have a named member?
106 *
107 * @param name name of member
108 * @return true if this object has a member of the given name
109 */
110 @Override
111 public boolean hasMember(final String name) {
112 return false;
113 }
115 /**
116 * Does this object have a indexed property?
117 *
118 * @param slot index to check
119 * @return true if this object has a slot
120 */
121 @Override
122 public boolean hasSlot(final int slot) {
123 return false;
124 }
126 /**
127 * Remove a named member from this JavaScript object
128 *
129 * @param name name of the member
130 */
131 @Override
132 public void removeMember(final String name) {
133 //empty
134 }
136 /**
137 * Set a named member in this JavaScript object
138 *
139 * @param name name of the member
140 * @param value value of the member
141 */
142 @Override
143 public void setMember(final String name, final Object value) {
144 //empty
145 }
147 /**
148 * Set an indexed member in this JavaScript object
149 *
150 * @param index index of the member slot
151 * @param value value of the member
152 */
153 @Override
154 public void setSlot(final int index, final Object value) {
155 //empty
156 }
158 // property and value iteration
160 /**
161 * Returns the set of all property names of this object.
162 *
163 * @return set of property names
164 */
165 @Override
166 public Set<String> keySet() {
167 return Collections.emptySet();
168 }
170 /**
171 * Returns the set of all property values of this object.
172 *
173 * @return set of property values.
174 */
175 @Override
176 public Collection<Object> values() {
177 return Collections.emptySet();
178 }
180 // JavaScript instanceof check
182 /**
183 * Checking whether the given object is an instance of 'this' object.
184 *
185 * @param instance instace to check
186 * @return true if the given 'instance' is an instance of this 'function' object
187 */
188 @Override
189 public boolean isInstance(final Object instance) {
190 return false;
191 }
193 /**
194 * Checking whether this object is an instance of the given 'clazz' object.
195 *
196 * @param clazz clazz to check
197 * @return true if this object is an instance of the given 'clazz'
198 */
199 @Override
200 public boolean isInstanceOf(final Object clazz) {
201 if (clazz instanceof JSObject) {
202 return ((JSObject)clazz).isInstance(this);
203 }
205 return false;
206 }
208 /**
209 * ECMA [[Class]] property
210 *
211 * @return ECMA [[Class]] property value of this object
212 */
213 @Override
214 public String getClassName() {
215 return getClass().getName();
216 }
218 /**
219 * Is this a function object?
220 *
221 * @return if this mirror wraps a ECMAScript function instance
222 */
223 @Override
224 public boolean isFunction() {
225 return false;
226 }
228 /**
229 * Is this a 'use strict' function object?
230 *
231 * @return true if this mirror represents a ECMAScript 'use strict' function
232 */
233 @Override
234 public boolean isStrictFunction() {
235 return false;
236 }
238 /**
239 * Is this an array object?
240 *
241 * @return if this mirror wraps a ECMAScript array object
242 */
243 @Override
244 public boolean isArray() {
245 return false;
246 }
248 /**
249 * Returns this object's numeric value.
250 *
251 * @return this object's numeric value.
252 * @deprecated use {@link #getDefaultValue(Class)} with {@link Number} hint instead.
253 */
254 @Override @Deprecated
255 public double toNumber() {
256 return JSType.toNumber(JSType.toPrimitive(this, Number.class));
257 }
259 /**
260 * Implements this object's {@code [[DefaultValue]]} method. The default implementation follows ECMAScript 5.1
261 * section 8.6.2 but subclasses are free to provide their own implementations.
262 *
263 * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}.
264 * @return this object's default value.
265 * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this
266 * exception into a JavaScript {@code TypeError}.
267 */
268 public Object getDefaultValue(final Class<?> hint) {
269 return DefaultValueImpl.getDefaultValue(this, hint);
270 }
272 /**
273 * When passed an {@link AbstractJSObject}, invokes its {@link #getDefaultValue(Class)} method. When passed any
274 * other {@link JSObject}, it will obtain its {@code [[DefaultValue]]} method as per ECMAScript 5.1 section
275 * 8.6.2.
276 *
277 * @param jsobj the {@link JSObject} whose {@code [[DefaultValue]]} is obtained.
278 * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}.
279 * @return this object's default value.
280 * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this
281 * exception into a JavaScript {@code TypeError}.
282 */
283 public static Object getDefaultValue(final JSObject jsobj, final Class<?> hint) {
284 if (jsobj instanceof AbstractJSObject) {
285 return ((AbstractJSObject)jsobj).getDefaultValue(hint);
286 } else if (jsobj instanceof JSONListAdapter) {
287 return ((JSONListAdapter)jsobj).getDefaultValue(hint);
288 }
289 return DefaultValueImpl.getDefaultValue(jsobj, hint);
290 }
291 }