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

Fri, 12 Jul 2013 20:06:41 +0530

author
sundar
date
Fri, 12 Jul 2013 20:06:41 +0530
changeset 437
5cdf4352ee0b
parent 414
ec84ba68ad39
child 456
e3307f1a30e5
permissions
-rw-r--r--

8020463: Input argument array wrapping in loadWithNewGlobal is wrong
Reviewed-by: attila, jlaskey

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

mercurial