325 } 326 }); 327 } 328 329 @Override 330 public Collection<Object> values() { 331 return inGlobal(new Callable<Collection<Object>>() { 332 @Override public Collection<Object> call() { 333 final List<Object> values = new ArrayList<>(size()); 334 final Iterator<Object> iter = sobj.valueIterator(); 335 336 while (iter.hasNext()) { 337 values.add(translateUndefined(wrap(iter.next(), global))); 338 } 339 340 return Collections.unmodifiableList(values); 341 } 342 }); 343 } 344 345 346 // These are public only so that Context can access these. 347 348 /** 349 * Make a script object mirror on given object if needed. 350 * 351 * @param obj object to be wrapped 352 * @param homeGlobal global to which this object belongs 353 * @return wrapped object 354 */ 355 public static Object wrap(final Object obj, final ScriptObject homeGlobal) { 356 return (obj instanceof ScriptObject) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj; 357 } 358 359 /** 360 * Unwrap a script object mirror if needed. 361 * 362 * @param obj object to be unwrapped 363 * @param homeGlobal global to which this object belongs 364 * @return unwrapped object | 325 } 326 }); 327 } 328 329 @Override 330 public Collection<Object> values() { 331 return inGlobal(new Callable<Collection<Object>>() { 332 @Override public Collection<Object> call() { 333 final List<Object> values = new ArrayList<>(size()); 334 final Iterator<Object> iter = sobj.valueIterator(); 335 336 while (iter.hasNext()) { 337 values.add(translateUndefined(wrap(iter.next(), global))); 338 } 339 340 return Collections.unmodifiableList(values); 341 } 342 }); 343 } 344 345 // Support for ECMAScript Object API on mirrors 346 347 /** 348 * Return the __proto__ of this object. 349 * @return __proto__ object. 350 */ 351 public Object getProto() { 352 return inGlobal(new Callable<Object>() { 353 @Override public Object call() { 354 return wrap(getScriptObject().getProto(), global); 355 } 356 }); 357 } 358 359 /** 360 * ECMA 8.12.1 [[GetOwnProperty]] (P) 361 * 362 * @param key property key 363 * 364 * @return Returns the Property Descriptor of the named own property of this 365 * object, or undefined if absent. 366 */ 367 public Object getOwnPropertyDescriptor(final String key) { 368 return inGlobal(new Callable<Object>() { 369 @Override public Object call() { 370 return wrap(getScriptObject().getOwnPropertyDescriptor(key), global); 371 } 372 }); 373 } 374 375 /** 376 * return an array of own property keys associated with the object. 377 * 378 * @param all True if to include non-enumerable keys. 379 * @return Array of keys. 380 */ 381 public String[] getOwnKeys(final boolean all) { 382 return inGlobal(new Callable<String[]>() { 383 @Override public String[] call() { 384 return getScriptObject().getOwnKeys(all); 385 } 386 }); 387 } 388 389 /** 390 * Flag this script object as non extensible 391 * 392 * @return the object after being made non extensible 393 */ 394 public ScriptObjectMirror preventExtensions() { 395 return inGlobal(new Callable<ScriptObjectMirror>() { 396 @Override public ScriptObjectMirror call() { 397 getScriptObject().preventExtensions(); 398 return ScriptObjectMirror.this; 399 } 400 }); 401 } 402 403 /** 404 * Check if this script object is extensible 405 * @return true if extensible 406 */ 407 public boolean isExtensible() { 408 return inGlobal(new Callable<Boolean>() { 409 @Override public Boolean call() { 410 return getScriptObject().isExtensible(); 411 } 412 }); 413 } 414 415 /** 416 * ECMAScript 15.2.3.8 - seal implementation 417 * @return the sealed script object 418 */ 419 public ScriptObjectMirror seal() { 420 return inGlobal(new Callable<ScriptObjectMirror>() { 421 @Override public ScriptObjectMirror call() { 422 getScriptObject().seal(); 423 return ScriptObjectMirror.this; 424 } 425 }); 426 } 427 428 /** 429 * Check whether this script object is sealed 430 * @return true if sealed 431 */ 432 public boolean isSealed() { 433 return inGlobal(new Callable<Boolean>() { 434 @Override public Boolean call() { 435 return getScriptObject().isSealed(); 436 } 437 }); 438 } 439 440 /** 441 * ECMA 15.2.39 - freeze implementation. Freeze this script object 442 * @return the frozen script object 443 */ 444 public ScriptObjectMirror freeze() { 445 return inGlobal(new Callable<ScriptObjectMirror>() { 446 @Override public ScriptObjectMirror call() { 447 getScriptObject().freeze(); 448 return ScriptObjectMirror.this; 449 } 450 }); 451 } 452 453 /** 454 * Check whether this script object is frozen 455 * @return true if frozen 456 */ 457 public boolean isFrozen() { 458 return inGlobal(new Callable<Boolean>() { 459 @Override public Boolean call() { 460 return getScriptObject().isFrozen(); 461 } 462 }); 463 } 464 465 // ECMAScript instanceof check 466 467 /** 468 * Checking whether a script object is an instance of another by 469 * walking the proto chain 470 * 471 * @param instance instace to check 472 * @return true if 'instance' is an instance of this object 473 */ 474 public boolean isInstance(final ScriptObjectMirror instance) { 475 // if not belongs to my global scope, return false 476 if (instance == null || global != instance.global) { 477 return false; 478 } 479 480 return inGlobal(new Callable<Boolean>() { 481 @Override public Boolean call() { 482 return getScriptObject().isInstance(instance.getScriptObject()); 483 } 484 }); 485 } 486 487 /** 488 * Utility to check if given object is ECMAScript undefined value 489 * 490 * @param obj object to check 491 * @return true if 'obj' is ECMAScript undefined value 492 */ 493 public static boolean isUndefined(final Object obj) { 494 return obj == ScriptRuntime.UNDEFINED; 495 } 496 497 /** 498 * is this a function object? 499 * 500 * @return if this mirror wraps a ECMAScript function instance 501 */ 502 public boolean isFunction() { 503 return getScriptObject() instanceof ScriptFunction; 504 } 505 506 /** 507 * is this a 'use strict' function object? 508 * 509 * @return true if this mirror represents a ECMAScript 'use strict' function 510 */ 511 public boolean isStrictFunction() { 512 return isFunction() && ((ScriptFunction)getScriptObject()).isStrict(); 513 } 514 515 /** 516 * is this an array object? 517 * 518 * @return if this mirror wraps a ECMAScript array object 519 */ 520 public boolean isArray() { 521 return getScriptObject().isArray(); 522 } 523 524 // These are public only so that Context can access these. 525 526 /** 527 * Make a script object mirror on given object if needed. 528 * 529 * @param obj object to be wrapped 530 * @param homeGlobal global to which this object belongs 531 * @return wrapped object 532 */ 533 public static Object wrap(final Object obj, final ScriptObject homeGlobal) { 534 return (obj instanceof ScriptObject) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj; 535 } 536 537 /** 538 * Unwrap a script object mirror if needed. 539 * 540 * @param obj object to be unwrapped 541 * @param homeGlobal global to which this object belongs 542 * @return unwrapped object |