src/jdk/nashorn/api/scripting/ScriptObjectMirror.java

Mon, 24 Jun 2013 19:06:01 +0530

author
sundar
date
Mon, 24 Jun 2013 19:06:01 +0530
changeset 376
51a5ee93d6bc
parent 350
3d947baa33cc
child 414
ec84ba68ad39
permissions
-rw-r--r--

8015959: Can't call foreign constructor
Reviewed-by: jlaskey, hannesw

jlaskey@3 1 /*
jlaskey@7 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jlaskey@3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jlaskey@3 4 *
jlaskey@3 5 * This code is free software; you can redistribute it and/or modify it
jlaskey@3 6 * under the terms of the GNU General Public License version 2 only, as
jlaskey@3 7 * published by the Free Software Foundation. Oracle designates this
jlaskey@3 8 * particular file as subject to the "Classpath" exception as provided
jlaskey@3 9 * by Oracle in the LICENSE file that accompanied this code.
jlaskey@3 10 *
jlaskey@3 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jlaskey@3 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jlaskey@3 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jlaskey@3 14 * version 2 for more details (a copy is included in the LICENSE file that
jlaskey@3 15 * accompanied this code).
jlaskey@3 16 *
jlaskey@3 17 * You should have received a copy of the GNU General Public License version
jlaskey@3 18 * 2 along with this work; if not, write to the Free Software Foundation,
jlaskey@3 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jlaskey@3 20 *
jlaskey@3 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jlaskey@3 22 * or visit www.oracle.com if you need additional information or have any
jlaskey@3 23 * questions.
jlaskey@3 24 */
jlaskey@3 25
jlaskey@3 26 package jdk.nashorn.api.scripting;
jlaskey@3 27
sundar@41 28 import java.security.AccessController;
sundar@41 29 import java.security.PrivilegedAction;
jlaskey@3 30 import java.util.AbstractMap;
jlaskey@3 31 import java.util.ArrayList;
jlaskey@3 32 import java.util.Collection;
jlaskey@3 33 import java.util.Collections;
sundar@321 34 import java.util.LinkedHashSet;
jlaskey@3 35 import java.util.Iterator;
jlaskey@3 36 import java.util.List;
jlaskey@3 37 import java.util.Map;
jlaskey@3 38 import java.util.Set;
jlaskey@3 39 import java.util.concurrent.Callable;
sundar@38 40 import javax.script.Bindings;
jlaskey@3 41 import jdk.nashorn.internal.runtime.Context;
jlaskey@3 42 import jdk.nashorn.internal.runtime.ScriptFunction;
jlaskey@3 43 import jdk.nashorn.internal.runtime.ScriptObject;
sundar@33 44 import jdk.nashorn.internal.runtime.ScriptRuntime;
jlaskey@3 45
jlaskey@3 46 /**
jlaskey@3 47 * Mirror object that wraps a given ScriptObject instance. User can
sundar@38 48 * access ScriptObject via the javax.script.Bindings interface or
sundar@38 49 * netscape.javascript.JSObject interface.
jlaskey@3 50 */
sundar@321 51 public final class ScriptObjectMirror extends JSObject implements Bindings {
jlaskey@3 52 private final ScriptObject sobj;
jlaskey@3 53 private final ScriptObject global;
jlaskey@3 54
jlaskey@3 55 ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) {
jlaskey@3 56 this.sobj = sobj;
jlaskey@3 57 this.global = global;
jlaskey@3 58 }
jlaskey@3 59
jlaskey@3 60 @Override
jlaskey@3 61 public boolean equals(final Object other) {
jlaskey@3 62 if (other instanceof ScriptObjectMirror) {
jlaskey@3 63 return sobj.equals(((ScriptObjectMirror)other).sobj);
jlaskey@3 64 }
jlaskey@3 65
jlaskey@3 66 return false;
jlaskey@3 67 }
jlaskey@3 68
jlaskey@3 69 @Override
jlaskey@3 70 public int hashCode() {
jlaskey@3 71 return sobj.hashCode();
jlaskey@3 72 }
jlaskey@3 73
sundar@33 74 @Override
sundar@33 75 public String toString() {
sundar@33 76 return inGlobal(new Callable<String>() {
sundar@33 77 @Override
sundar@33 78 public String call() {
sundar@33 79 return ScriptRuntime.safeToString(sobj);
sundar@33 80 }
sundar@33 81 });
sundar@33 82 }
sundar@33 83
jlaskey@3 84 private <V> V inGlobal(final Callable<V> callable) {
sundar@44 85 final ScriptObject oldGlobal = NashornScriptEngine.getNashornGlobal();
jlaskey@3 86 final boolean globalChanged = (oldGlobal != global);
jlaskey@3 87 if (globalChanged) {
jlaskey@3 88 NashornScriptEngine.setNashornGlobal(global);
jlaskey@3 89 }
jlaskey@3 90 try {
jlaskey@3 91 return callable.call();
jlaskey@3 92 } catch (final RuntimeException e) {
jlaskey@3 93 throw e;
jlaskey@3 94 } catch (final Exception e) {
jlaskey@3 95 throw new AssertionError("Cannot happen", e);
jlaskey@3 96 } finally {
jlaskey@3 97 if (globalChanged) {
jlaskey@3 98 NashornScriptEngine.setNashornGlobal(oldGlobal);
jlaskey@3 99 }
jlaskey@3 100 }
jlaskey@3 101 }
jlaskey@3 102
jlaskey@3 103 // JSObject methods
jlaskey@3 104 @Override
sundar@376 105 public Object call(final String functionName, final Object... args) {
sundar@44 106 final ScriptObject oldGlobal = NashornScriptEngine.getNashornGlobal();
jlaskey@3 107 final boolean globalChanged = (oldGlobal != global);
jlaskey@3 108
sundar@88 109 try {
sundar@88 110 if (globalChanged) {
sundar@88 111 NashornScriptEngine.setNashornGlobal(global);
jlaskey@3 112 }
jlaskey@3 113
sundar@376 114 final Object val = functionName == null? sobj : sobj.get(functionName);
sundar@88 115 if (! (val instanceof ScriptFunction)) {
sundar@376 116 throw new RuntimeException("No such function " + ((functionName != null)? functionName : ""));
jlaskey@3 117 }
jlaskey@3 118
sundar@88 119 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
sundar@88 120 return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
sundar@88 121 } catch (final RuntimeException | Error e) {
sundar@88 122 throw e;
sundar@88 123 } catch (final Throwable t) {
sundar@88 124 throw new RuntimeException(t);
sundar@88 125 } finally {
sundar@88 126 if (globalChanged) {
sundar@88 127 NashornScriptEngine.setNashornGlobal(oldGlobal);
sundar@88 128 }
sundar@88 129 }
jlaskey@3 130 }
jlaskey@3 131
jlaskey@3 132 @Override
sundar@376 133 public Object newObject(final String functionName, final Object... args) {
sundar@376 134 final ScriptObject oldGlobal = NashornScriptEngine.getNashornGlobal();
sundar@376 135 final boolean globalChanged = (oldGlobal != global);
sundar@376 136
sundar@376 137 try {
sundar@376 138 if (globalChanged) {
sundar@376 139 NashornScriptEngine.setNashornGlobal(global);
sundar@376 140 }
sundar@376 141
sundar@376 142 final Object val = functionName == null? sobj : sobj.get(functionName);
sundar@376 143 if (! (val instanceof ScriptFunction)) {
sundar@376 144 throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : ""));
sundar@376 145 }
sundar@376 146
sundar@376 147 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
sundar@376 148 return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global);
sundar@376 149 } catch (final RuntimeException | Error e) {
sundar@376 150 throw e;
sundar@376 151 } catch (final Throwable t) {
sundar@376 152 throw new RuntimeException(t);
sundar@376 153 } finally {
sundar@376 154 if (globalChanged) {
sundar@376 155 NashornScriptEngine.setNashornGlobal(oldGlobal);
sundar@376 156 }
sundar@376 157 }
sundar@376 158 }
sundar@376 159
sundar@376 160 @Override
jlaskey@3 161 public Object eval(final String s) {
jlaskey@3 162 return inGlobal(new Callable<Object>() {
jlaskey@3 163 @Override
jlaskey@3 164 public Object call() {
sundar@41 165 final Context context = AccessController.doPrivileged(
sundar@41 166 new PrivilegedAction<Context>() {
sundar@41 167 @Override
sundar@41 168 public Context run() {
sundar@41 169 return Context.getContext();
sundar@41 170 }
sundar@41 171 });
sundar@41 172 return wrap(context.eval(global, s, null, null, false), global);
jlaskey@3 173 }
jlaskey@3 174 });
jlaskey@3 175 }
jlaskey@3 176
jlaskey@3 177 @Override
jlaskey@3 178 public Object getMember(final String name) {
sundar@38 179 return inGlobal(new Callable<Object>() {
sundar@38 180 @Override public Object call() {
sundar@38 181 return wrap(sobj.get(name), global);
sundar@38 182 }
sundar@38 183 });
jlaskey@3 184 }
jlaskey@3 185
jlaskey@3 186 @Override
jlaskey@3 187 public Object getSlot(final int index) {
sundar@38 188 return inGlobal(new Callable<Object>() {
sundar@38 189 @Override public Object call() {
sundar@38 190 return wrap(sobj.get(index), global);
sundar@38 191 }
sundar@38 192 });
jlaskey@3 193 }
jlaskey@3 194
jlaskey@3 195 @Override
jlaskey@3 196 public void removeMember(final String name) {
jlaskey@3 197 remove(name);
jlaskey@3 198 }
jlaskey@3 199
jlaskey@3 200 @Override
jlaskey@3 201 public void setMember(final String name, final Object value) {
sundar@88 202 put(name, value);
jlaskey@3 203 }
jlaskey@3 204
jlaskey@3 205 @Override
jlaskey@3 206 public void setSlot(final int index, final Object value) {
sundar@38 207 inGlobal(new Callable<Void>() {
sundar@38 208 @Override public Void call() {
sundar@41 209 sobj.set(index, unwrap(value, global), global.isStrictContext());
sundar@38 210 return null;
sundar@38 211 }
sundar@38 212 });
jlaskey@3 213 }
jlaskey@3 214
jlaskey@3 215 @Override
jlaskey@3 216 public void clear() {
jlaskey@3 217 inGlobal(new Callable<Object>() {
jlaskey@3 218 @Override public Object call() {
jlaskey@3 219 sobj.clear();
jlaskey@3 220 return null;
sundar@38 221 }
sundar@38 222 });
jlaskey@3 223 }
jlaskey@3 224
jlaskey@3 225 @Override
jlaskey@3 226 public boolean containsKey(final Object key) {
jlaskey@3 227 return inGlobal(new Callable<Boolean>() {
jlaskey@3 228 @Override public Boolean call() {
jlaskey@3 229 return sobj.containsKey(unwrap(key, global));
sundar@38 230 }
sundar@38 231 });
jlaskey@3 232 }
jlaskey@3 233
jlaskey@3 234 @Override
jlaskey@3 235 public boolean containsValue(final Object value) {
jlaskey@3 236 return inGlobal(new Callable<Boolean>() {
jlaskey@3 237 @Override public Boolean call() {
jlaskey@3 238 return sobj.containsValue(unwrap(value, global));
sundar@38 239 }
sundar@38 240 });
jlaskey@3 241 }
jlaskey@3 242
jlaskey@3 243 @Override
sundar@38 244 public Set<Map.Entry<String, Object>> entrySet() {
sundar@38 245 return inGlobal(new Callable<Set<Map.Entry<String, Object>>>() {
sundar@38 246 @Override public Set<Map.Entry<String, Object>> call() {
jlaskey@3 247 final Iterator<String> iter = sobj.propertyIterator();
sundar@321 248 final Set<Map.Entry<String, Object>> entries = new LinkedHashSet<>();
jlaskey@3 249
jlaskey@3 250 while (iter.hasNext()) {
sundar@38 251 final String key = iter.next();
sundar@38 252 final Object value = translateUndefined(wrap(sobj.get(key), global));
jlaskey@3 253 entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value));
jlaskey@3 254 }
jlaskey@3 255
jlaskey@3 256 return Collections.unmodifiableSet(entries);
jlaskey@3 257 }
jlaskey@3 258 });
jlaskey@3 259 }
jlaskey@3 260
jlaskey@3 261 @Override
jlaskey@3 262 public Object get(final Object key) {
sundar@38 263 return inGlobal(new Callable<Object>() {
sundar@38 264 @Override public Object call() {
sundar@38 265 return translateUndefined(wrap(sobj.get(key), global));
sundar@38 266 }
sundar@38 267 });
jlaskey@3 268 }
jlaskey@3 269
jlaskey@3 270 @Override
jlaskey@3 271 public boolean isEmpty() {
sundar@38 272 return inGlobal(new Callable<Boolean>() {
sundar@38 273 @Override public Boolean call() {
sundar@38 274 return sobj.isEmpty();
sundar@38 275 }
sundar@38 276 });
jlaskey@3 277 }
jlaskey@3 278
jlaskey@3 279 @Override
sundar@38 280 public Set<String> keySet() {
sundar@38 281 return inGlobal(new Callable<Set<String>>() {
sundar@38 282 @Override public Set<String> call() {
sundar@38 283 final Iterator<String> iter = sobj.propertyIterator();
sundar@321 284 final Set<String> keySet = new LinkedHashSet<>();
jlaskey@3 285
sundar@38 286 while (iter.hasNext()) {
sundar@38 287 keySet.add(iter.next());
sundar@38 288 }
sundar@38 289
sundar@38 290 return Collections.unmodifiableSet(keySet);
jlaskey@3 291 }
sundar@38 292 });
jlaskey@3 293 }
jlaskey@3 294
jlaskey@3 295 @Override
sundar@38 296 public Object put(final String key, final Object value) {
sundar@88 297 final ScriptObject oldGlobal = NashornScriptEngine.getNashornGlobal();
sundar@88 298 final boolean globalChanged = (oldGlobal != global);
jlaskey@3 299 return inGlobal(new Callable<Object>() {
jlaskey@3 300 @Override public Object call() {
sundar@88 301 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
sundar@88 302 return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global)), global));
sundar@38 303 }
sundar@38 304 });
jlaskey@3 305 }
jlaskey@3 306
jlaskey@3 307 @Override
sundar@38 308 public void putAll(final Map<? extends String, ? extends Object> map) {
sundar@88 309 final ScriptObject oldGlobal = NashornScriptEngine.getNashornGlobal();
sundar@88 310 final boolean globalChanged = (oldGlobal != global);
sundar@41 311 final boolean strict = sobj.isStrictContext();
sundar@38 312 inGlobal(new Callable<Object>() {
sundar@38 313 @Override public Object call() {
sundar@38 314 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
sundar@88 315 final Object value = entry.getValue();
sundar@88 316 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
sundar@88 317 sobj.set(entry.getKey(), unwrap(modValue, global), strict);
sundar@38 318 }
sundar@38 319 return null;
jlaskey@3 320 }
sundar@38 321 });
jlaskey@3 322 }
jlaskey@3 323
jlaskey@3 324 @Override
jlaskey@3 325 public Object remove(final Object key) {
jlaskey@3 326 return inGlobal(new Callable<Object>() {
jlaskey@3 327 @Override public Object call() {
jlaskey@3 328 return wrap(sobj.remove(unwrap(key, global)), global);
jlaskey@3 329 }
jlaskey@3 330 });
jlaskey@3 331 }
jlaskey@3 332
sundar@321 333 /**
sundar@321 334 * Delete a property from this object.
sundar@321 335 *
sundar@321 336 * @param key the property to be deleted
sundar@321 337 *
sundar@321 338 * @return if the delete was successful or not
sundar@321 339 */
sundar@321 340 public boolean delete(final Object key) {
sundar@321 341 return inGlobal(new Callable<Boolean>() {
sundar@321 342 @Override public Boolean call() {
sundar@321 343 return sobj.delete(unwrap(key, global));
sundar@321 344 }
sundar@321 345 });
sundar@321 346 }
sundar@321 347
jlaskey@3 348 @Override
jlaskey@3 349 public int size() {
jlaskey@3 350 return inGlobal(new Callable<Integer>() {
jlaskey@3 351 @Override public Integer call() {
jlaskey@3 352 return sobj.size();
jlaskey@3 353 }
jlaskey@3 354 });
jlaskey@3 355 }
jlaskey@3 356
jlaskey@3 357 @Override
jlaskey@3 358 public Collection<Object> values() {
sundar@38 359 return inGlobal(new Callable<Collection<Object>>() {
sundar@38 360 @Override public Collection<Object> call() {
sundar@38 361 final List<Object> values = new ArrayList<>(size());
sundar@38 362 final Iterator<Object> iter = sobj.valueIterator();
jlaskey@3 363
sundar@38 364 while (iter.hasNext()) {
sundar@88 365 values.add(translateUndefined(wrap(iter.next(), global)));
sundar@38 366 }
sundar@38 367
sundar@38 368 return Collections.unmodifiableList(values);
jlaskey@3 369 }
sundar@38 370 });
sundar@38 371 }
jlaskey@3 372
sundar@350 373 // Support for ECMAScript Object API on mirrors
sundar@350 374
sundar@350 375 /**
sundar@350 376 * Return the __proto__ of this object.
sundar@350 377 * @return __proto__ object.
sundar@350 378 */
sundar@350 379 public Object getProto() {
sundar@350 380 return inGlobal(new Callable<Object>() {
sundar@350 381 @Override public Object call() {
sundar@350 382 return wrap(getScriptObject().getProto(), global);
sundar@350 383 }
sundar@350 384 });
sundar@350 385 }
sundar@350 386
sundar@350 387 /**
sundar@350 388 * ECMA 8.12.1 [[GetOwnProperty]] (P)
sundar@350 389 *
sundar@350 390 * @param key property key
sundar@350 391 *
sundar@350 392 * @return Returns the Property Descriptor of the named own property of this
sundar@350 393 * object, or undefined if absent.
sundar@350 394 */
sundar@350 395 public Object getOwnPropertyDescriptor(final String key) {
sundar@350 396 return inGlobal(new Callable<Object>() {
sundar@350 397 @Override public Object call() {
sundar@350 398 return wrap(getScriptObject().getOwnPropertyDescriptor(key), global);
sundar@350 399 }
sundar@350 400 });
sundar@350 401 }
sundar@350 402
sundar@350 403 /**
sundar@350 404 * return an array of own property keys associated with the object.
sundar@350 405 *
sundar@350 406 * @param all True if to include non-enumerable keys.
sundar@350 407 * @return Array of keys.
sundar@350 408 */
sundar@350 409 public String[] getOwnKeys(final boolean all) {
sundar@350 410 return inGlobal(new Callable<String[]>() {
sundar@350 411 @Override public String[] call() {
sundar@350 412 return getScriptObject().getOwnKeys(all);
sundar@350 413 }
sundar@350 414 });
sundar@350 415 }
sundar@350 416
sundar@350 417 /**
sundar@350 418 * Flag this script object as non extensible
sundar@350 419 *
sundar@350 420 * @return the object after being made non extensible
sundar@350 421 */
sundar@350 422 public ScriptObjectMirror preventExtensions() {
sundar@350 423 return inGlobal(new Callable<ScriptObjectMirror>() {
sundar@350 424 @Override public ScriptObjectMirror call() {
sundar@350 425 getScriptObject().preventExtensions();
sundar@350 426 return ScriptObjectMirror.this;
sundar@350 427 }
sundar@350 428 });
sundar@350 429 }
sundar@350 430
sundar@350 431 /**
sundar@350 432 * Check if this script object is extensible
sundar@350 433 * @return true if extensible
sundar@350 434 */
sundar@350 435 public boolean isExtensible() {
sundar@350 436 return inGlobal(new Callable<Boolean>() {
sundar@350 437 @Override public Boolean call() {
sundar@350 438 return getScriptObject().isExtensible();
sundar@350 439 }
sundar@350 440 });
sundar@350 441 }
sundar@350 442
sundar@350 443 /**
sundar@350 444 * ECMAScript 15.2.3.8 - seal implementation
sundar@350 445 * @return the sealed script object
sundar@350 446 */
sundar@350 447 public ScriptObjectMirror seal() {
sundar@350 448 return inGlobal(new Callable<ScriptObjectMirror>() {
sundar@350 449 @Override public ScriptObjectMirror call() {
sundar@350 450 getScriptObject().seal();
sundar@350 451 return ScriptObjectMirror.this;
sundar@350 452 }
sundar@350 453 });
sundar@350 454 }
sundar@350 455
sundar@350 456 /**
sundar@350 457 * Check whether this script object is sealed
sundar@350 458 * @return true if sealed
sundar@350 459 */
sundar@350 460 public boolean isSealed() {
sundar@350 461 return inGlobal(new Callable<Boolean>() {
sundar@350 462 @Override public Boolean call() {
sundar@350 463 return getScriptObject().isSealed();
sundar@350 464 }
sundar@350 465 });
sundar@350 466 }
sundar@350 467
sundar@350 468 /**
sundar@350 469 * ECMA 15.2.39 - freeze implementation. Freeze this script object
sundar@350 470 * @return the frozen script object
sundar@350 471 */
sundar@350 472 public ScriptObjectMirror freeze() {
sundar@350 473 return inGlobal(new Callable<ScriptObjectMirror>() {
sundar@350 474 @Override public ScriptObjectMirror call() {
sundar@350 475 getScriptObject().freeze();
sundar@350 476 return ScriptObjectMirror.this;
sundar@350 477 }
sundar@350 478 });
sundar@350 479 }
sundar@350 480
sundar@350 481 /**
sundar@350 482 * Check whether this script object is frozen
sundar@350 483 * @return true if frozen
sundar@350 484 */
sundar@350 485 public boolean isFrozen() {
sundar@350 486 return inGlobal(new Callable<Boolean>() {
sundar@350 487 @Override public Boolean call() {
sundar@350 488 return getScriptObject().isFrozen();
sundar@350 489 }
sundar@350 490 });
sundar@350 491 }
sundar@350 492
sundar@350 493 // ECMAScript instanceof check
sundar@350 494
sundar@350 495 /**
sundar@350 496 * Checking whether a script object is an instance of another by
sundar@350 497 * walking the proto chain
sundar@350 498 *
sundar@350 499 * @param instance instace to check
sundar@350 500 * @return true if 'instance' is an instance of this object
sundar@350 501 */
sundar@350 502 public boolean isInstance(final ScriptObjectMirror instance) {
sundar@350 503 // if not belongs to my global scope, return false
sundar@350 504 if (instance == null || global != instance.global) {
sundar@350 505 return false;
sundar@350 506 }
sundar@350 507
sundar@350 508 return inGlobal(new Callable<Boolean>() {
sundar@350 509 @Override public Boolean call() {
sundar@350 510 return getScriptObject().isInstance(instance.getScriptObject());
sundar@350 511 }
sundar@350 512 });
sundar@350 513 }
sundar@350 514
sundar@350 515 /**
sundar@350 516 * Utility to check if given object is ECMAScript undefined value
sundar@350 517 *
sundar@350 518 * @param obj object to check
sundar@350 519 * @return true if 'obj' is ECMAScript undefined value
sundar@350 520 */
sundar@350 521 public static boolean isUndefined(final Object obj) {
sundar@350 522 return obj == ScriptRuntime.UNDEFINED;
sundar@350 523 }
sundar@350 524
sundar@350 525 /**
sundar@350 526 * is this a function object?
sundar@350 527 *
sundar@350 528 * @return if this mirror wraps a ECMAScript function instance
sundar@350 529 */
sundar@350 530 public boolean isFunction() {
sundar@350 531 return getScriptObject() instanceof ScriptFunction;
sundar@350 532 }
sundar@350 533
sundar@350 534 /**
sundar@350 535 * is this a 'use strict' function object?
sundar@350 536 *
sundar@350 537 * @return true if this mirror represents a ECMAScript 'use strict' function
sundar@350 538 */
sundar@350 539 public boolean isStrictFunction() {
sundar@350 540 return isFunction() && ((ScriptFunction)getScriptObject()).isStrict();
sundar@350 541 }
sundar@350 542
sundar@350 543 /**
sundar@350 544 * is this an array object?
sundar@350 545 *
sundar@350 546 * @return if this mirror wraps a ECMAScript array object
sundar@350 547 */
sundar@350 548 public boolean isArray() {
sundar@350 549 return getScriptObject().isArray();
sundar@350 550 }
sundar@45 551
sundar@322 552 // These are public only so that Context can access these.
jlaskey@3 553
sundar@322 554 /**
sundar@322 555 * Make a script object mirror on given object if needed.
sundar@322 556 *
sundar@322 557 * @param obj object to be wrapped
sundar@322 558 * @param homeGlobal global to which this object belongs
sundar@322 559 * @return wrapped object
sundar@322 560 */
sundar@322 561 public static Object wrap(final Object obj, final ScriptObject homeGlobal) {
jlaskey@3 562 return (obj instanceof ScriptObject) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj;
jlaskey@3 563 }
jlaskey@3 564
sundar@322 565 /**
sundar@322 566 * Unwrap a script object mirror if needed.
sundar@322 567 *
sundar@322 568 * @param obj object to be unwrapped
sundar@322 569 * @param homeGlobal global to which this object belongs
sundar@322 570 * @return unwrapped object
sundar@322 571 */
sundar@322 572 public static Object unwrap(final Object obj, final ScriptObject homeGlobal) {
jlaskey@3 573 if (obj instanceof ScriptObjectMirror) {
jlaskey@3 574 final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
jlaskey@3 575 return (mirror.global == homeGlobal)? mirror.sobj : obj;
jlaskey@3 576 }
jlaskey@3 577
jlaskey@3 578 return obj;
jlaskey@3 579 }
jlaskey@3 580
sundar@322 581 /**
sundar@322 582 * Wrap an array of object to script object mirrors if needed.
sundar@322 583 *
sundar@322 584 * @param args array to be unwrapped
sundar@322 585 * @param homeGlobal global to which this object belongs
sundar@322 586 * @return wrapped array
sundar@322 587 */
sundar@322 588 public static Object[] wrapArray(final Object[] args, final ScriptObject homeGlobal) {
jlaskey@3 589 if (args == null || args.length == 0) {
jlaskey@3 590 return args;
jlaskey@3 591 }
jlaskey@3 592
jlaskey@3 593 final Object[] newArgs = new Object[args.length];
jlaskey@3 594 int index = 0;
jlaskey@3 595 for (final Object obj : args) {
jlaskey@3 596 newArgs[index] = wrap(obj, homeGlobal);
jlaskey@3 597 index++;
jlaskey@3 598 }
jlaskey@3 599 return newArgs;
jlaskey@3 600 }
jlaskey@3 601
sundar@322 602 /**
sundar@322 603 * Unwrap an array of script object mirrors if needed.
sundar@322 604 *
sundar@322 605 * @param args array to be unwrapped
sundar@322 606 * @param homeGlobal global to which this object belongs
sundar@322 607 * @return unwrapped array
sundar@322 608 */
sundar@322 609 public static Object[] unwrapArray(final Object[] args, final ScriptObject homeGlobal) {
jlaskey@3 610 if (args == null || args.length == 0) {
jlaskey@3 611 return args;
jlaskey@3 612 }
jlaskey@3 613
jlaskey@3 614 final Object[] newArgs = new Object[args.length];
jlaskey@3 615 int index = 0;
jlaskey@3 616 for (final Object obj : args) {
jlaskey@3 617 newArgs[index] = unwrap(obj, homeGlobal);
jlaskey@3 618 index++;
jlaskey@3 619 }
jlaskey@3 620 return newArgs;
jlaskey@3 621 }
sundar@322 622
sundar@322 623 // package-privates below this.
sundar@322 624 ScriptObject getScriptObject() {
sundar@322 625 return sobj;
sundar@322 626 }
sundar@322 627
sundar@322 628 static Object translateUndefined(Object obj) {
sundar@322 629 return (obj == ScriptRuntime.UNDEFINED)? null : obj;
sundar@322 630 }
jlaskey@3 631 }

mercurial