/** * Creates a List from a V8Array using a deep copy and a TypeAdapter to handle * type conversions. All elements in the V8Array are released after they are accessed. * However, the root array itself is not released. * * @param array The root of the V8Array graph. * @param adapter The {@link TypeAdapter} to use for the object conversions. * * @return A list representing a deep copy of the V8Array rooted at 'array'. */ public static List<? super Object> toList(final V8Array array, final TypeAdapter adapter) { V8Map<Object> cache = new V8Map<Object>(); try { return toList(array, cache, adapter); } finally { cache.close(); } }
@Override public void close() { this.clear(); }
@SuppressWarnings("unchecked") private static List<? super Object> toList(final V8Array array, final V8Map<Object> cache, final TypeAdapter adapter) { if (array == null) { return Collections.emptyList(); } if (cache.containsKey(array)) { return (List<? super Object>) cache.get(array); } List<? super Object> result = new ArrayList<Object>(); cache.put(array, result); for (int i = 0; i < array.length(); i++) { Object object = null; int type = V8Value.UNDEFINED; try { object = array.get(i); type = array.getType(i); Object value = getValue(object, type, cache, adapter); if (value != IGNORE) { result.add(value); } } finally { if (object instanceof Releasable) { ((Releasable) object).release(); } } } return result; }
/** * Registers an executor with this runtime. An executor is another * runtime with its own thread. By registering an executor, it can be * terminated when this runtime is released. * * @param key The key to associate the executor with. * @param executor The executor itself. */ public void registerV8Executor(final V8Object key, final V8Executor executor) { checkThread(); if (executors == null) { executors = new V8Map<V8Executor>(); } executors.put(key, executor); }
@Test public void testAddAllWithDuplicates() { V8Map<String> map = new V8Map<String>(); V8Object v1 = new V8Object(v8); map.put(v1, "foo"); V8Map<String> newMap = new V8Map<String>(); newMap.put(v1, "bar"); v1.close(); newMap.putAll(map); map.close(); assertEquals(1, newMap.size()); assertEquals("foo", newMap.values().iterator().next()); newMap.close(); }
@Test public void testContainsKey() { V8Map<String> map = new V8Map<String>(); v8.executeVoidScript("var x = {}"); V8Object v8Object = v8.getObject("x"); map.put(v8Object, "foo"); assertTrue(map.containsKey(v8Object)); v8Object.close(); map.close(); }
/** * Creates a Map from a V8Object using a deep copy. All elements * in the V8Object are released after they are accessed. However, the root * object itself is not released. * * @param object The root of the V8Object graph. * * @return A map representing a deep copy of the V8Object rooted at 'object'. */ public static Map<String, ? super Object> toMap(final V8Object object) { V8Map<Object> cache = new V8Map<Object>(); try { return toMap(object, cache); } finally { cache.release(); } }
@Test public void testEntrySet() { V8Map<String> map = new V8Map<String>(); V8Object v1 = new V8Object(v8); map.put(v1, "foo"); Set<Entry<V8Value, String>> entrySet = map.entrySet(); assertEquals(1, entrySet.size()); assertEquals(v1, entrySet.iterator().next().getKey()); assertEquals("foo", entrySet.iterator().next().getValue()); v1.close(); map.close(); }
@Test public void testContainsValue() { V8Map<String> map = new V8Map<String>(); v8.executeVoidScript("var x = {}"); V8Object v8Object = v8.getObject("x"); map.put(v8Object, "foo"); assertTrue(map.containsValue("foo")); v8Object.close(); map.close(); }
@Test public void testDoesNotContainKey() { V8Map<String> map = new V8Map<String>(); v8.executeVoidScript("var x = {}"); V8Object v8Object = v8.getObject("x"); assertFalse(map.containsKey(v8Object)); v8Object.close(); map.close(); }
@Override public V put(final V8Value key, final V value) { this.remove(key); V8Value twin = key.twin(); twinMap.put(twin, twin); return map.put(twin, value); }