Browse Source

Merge branch 'release/10.0' of http://cloud.finedevelop.com:2015/scm/~harrison/base-third into release/10.0

bugfix/10.0
Harrison 5 years ago
parent
commit
fac226125f
  1. 158
      fine-j2v8/src/com/eclipsesource/v8/LibraryLoader.java
  2. 36
      fine-j2v8/src/com/eclipsesource/v8/NodeJS.java
  3. 12
      fine-j2v8/src/com/eclipsesource/v8/Platform.java
  4. 316
      fine-j2v8/src/com/eclipsesource/v8/PlatformDetector.java
  5. 10
      fine-j2v8/src/com/eclipsesource/v8/Releasable.java
  6. 208
      fine-j2v8/src/com/eclipsesource/v8/V8.java
  7. 62
      fine-j2v8/src/com/eclipsesource/v8/V8Array.java
  8. 401
      fine-j2v8/src/com/eclipsesource/v8/V8ArrayBuffer.java
  9. 15
      fine-j2v8/src/com/eclipsesource/v8/V8Function.java
  10. 53
      fine-j2v8/src/com/eclipsesource/v8/V8Locker.java
  11. 45
      fine-j2v8/src/com/eclipsesource/v8/V8Object.java
  12. 62
      fine-j2v8/src/com/eclipsesource/v8/V8TypedArray.java
  13. 103
      fine-j2v8/src/com/eclipsesource/v8/V8Value.java
  14. 43
      fine-j2v8/src/com/eclipsesource/v8/debug/DebugHandler.java
  15. 10
      fine-j2v8/src/com/eclipsesource/v8/debug/EventData.java
  16. 16
      fine-j2v8/src/com/eclipsesource/v8/debug/ExecutionState.java
  17. 11
      fine-j2v8/src/com/eclipsesource/v8/debug/ScriptBreakPoint.java
  18. 693
      fine-j2v8/src/com/eclipsesource/v8/debug/V8DebugServer.java
  19. 44
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Frame.java
  20. 20
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/FunctionMirror.java
  21. 18
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Mirror.java
  22. 8
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/ObjectMirror.java
  23. 20
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/PropertiesArray.java
  24. 2
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/PropertyMirror.java
  25. 12
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Scope.java
  26. 30
      fine-j2v8/src/com/eclipsesource/v8/debug/mirror/SourceLocation.java
  27. 69
      fine-j2v8/src/com/eclipsesource/v8/utils/ArrayBuffer.java
  28. 94
      fine-j2v8/src/com/eclipsesource/v8/utils/ConcurrentV8.java
  29. 2
      fine-j2v8/src/com/eclipsesource/v8/utils/MemoryManager.java
  30. 55
      fine-j2v8/src/com/eclipsesource/v8/utils/SingleTypeAdapter.java
  31. 39
      fine-j2v8/src/com/eclipsesource/v8/utils/TypeAdapter.java
  32. 73
      fine-j2v8/src/com/eclipsesource/v8/utils/TypedArray.java
  33. 6
      fine-j2v8/src/com/eclipsesource/v8/utils/V8Executor.java
  34. 20
      fine-j2v8/src/com/eclipsesource/v8/utils/V8Map.java
  35. 440
      fine-j2v8/src/com/eclipsesource/v8/utils/V8ObjectUtils.java
  36. 4
      fine-j2v8/src/com/eclipsesource/v8/utils/V8PropertyMap.java
  37. 2
      fine-j2v8/src/com/eclipsesource/v8/utils/V8Thread.java
  38. 109
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java
  39. 79
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Float32Array.java
  40. 79
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Float64Array.java
  41. 79
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int16Array.java
  42. 75
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int32Array.java
  43. 78
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int8Array.java
  44. 58
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/TypedArray.java
  45. 79
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java
  46. 79
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java
  47. 78
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java
  48. 87
      fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java
  49. BIN
      fine-j2v8/src/libj2v8-linux-x86_64.so
  50. BIN
      fine-j2v8/src/libj2v8-macosx-x86_64.dylib
  51. BIN
      fine-j2v8/src/libj2v8-windows-x86_64.dll

158
fine-j2v8/src/com/eclipsesource/v8/LibraryLoader.java

@ -7,6 +7,7 @@
*
* Contributors:
* EclipseSource - initial API and implementation
* Wolfgang Steiner - code separation PlatformDetector/LibraryLoader
******************************************************************************/
package com.eclipsesource.v8;
@ -27,49 +28,86 @@ class LibraryLoader {
SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$
}
private static String computeLibraryShortName() {
String base = "j2v8";
String osSuffix = getOS();
String archSuffix = getArchSuffix();
return base + "_" + osSuffix + "_" + archSuffix;
}
/**
* Returns the base-name for the native J2V8 library file.
* @param withLinuxVendor include/exclude the {vendor} part from the returned filename
* <p>NOTE: Vendors are only included for linux systems</p>
* @return The filename string has the following structure:
* <pre><code>{arch}-[vendor]-{operating_system}</pre></code>
*/
public static String computeLibraryShortName(boolean withLinuxVendor) {
String prefix = "j2v8";
String vendor = withLinuxVendor && PlatformDetector.OS.isLinux() ? PlatformDetector.Vendor.getName() : null;
String os = PlatformDetector.OS.getName();
String arch = PlatformDetector.Arch.getName();
final String separator = "-";
private static String computeLibraryFullName() {
return "lib" + computeLibraryShortName() + "." + getOSFileExtension();
return
prefix +
(vendor != null ? separator + vendor : "") +
separator + os +
separator + arch;
}
static void loadLibrary(final String tempDirectory) {
if ( isAndroid() ) {
System.loadLibrary("j2v8");
return;
public static String computeLibraryFullName(boolean withLinuxVendor) {
return "lib" + computeLibraryShortName(withLinuxVendor) + "." + PlatformDetector.OS.getLibFileExtension();
}
StringBuffer message = new StringBuffer();
String libShortName = computeLibraryShortName();
String libFullName = computeLibraryFullName();
String ideLocation = System.getProperty("user.dir") + SEPARATOR + "jni" + SEPARATOR + computeLibraryFullName();
String path = null;
static boolean tryLoad(boolean withLinuxVendor, StringBuffer message) {
String libShortName = computeLibraryShortName(withLinuxVendor);
String libFullName = computeLibraryFullName(withLinuxVendor);
String ideLocation = System.getProperty("user.dir") + SEPARATOR + "jni" + SEPARATOR + libFullName;
/* Try loading library from java library path */
if (load(libFullName, message)) {
return true;
}
if (load(libShortName, message)) {
return;
return true;
}
/* Try loading library from the IDE location */
if (new File(ideLocation).exists()) {
if (load(ideLocation, message)) {
return;
return true;
}
}
return false;
}
static void loadLibrary(final String tempDirectory) {
if (PlatformDetector.OS.isAndroid()) {
System.loadLibrary("j2v8");
return;
}
StringBuffer message = new StringBuffer();
// try loading a vendor-specific library first
if (tryLoad(true, message))
return;
// if there is no vendor-specific library, just try to load the default OS library
if (tryLoad(false, message))
return;
String path = null;
if (tempDirectory != null) {
path = tempDirectory;
} else {
path = System.getProperty("user.home"); //$NON-NLS-1$
path = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$
}
if (extract(path + SEPARATOR + libFullName, libFullName, message)) {
// try extracting a vendor-specific library first
if (extract(path, true, message))
return;
// if there is no vendor-specific library, just try to extract the default OS library
if (extract(path, false, message))
return;
}
/* Failed to find the library */
throw new UnsatisfiedLinkError("Could not load J2V8 library. Reasons: " + message.toString()); //$NON-NLS-1$
@ -94,10 +132,17 @@ class LibraryLoader {
return false;
}
static boolean extract(String libPath, boolean withLinuxVendor, StringBuffer message) {
String libFullName = computeLibraryFullName(withLinuxVendor);
return extract(libPath + SEPARATOR + libFullName, libFullName, message);
}
static boolean extract(final String fileName, final String mappedName, final StringBuffer message) {
FileOutputStream os = null;
InputStream is = null;
File file = new File(fileName);
//这部分自己修改过,主要是以为linux通过System.getProperty("java.io.tmpdir")获取到的是相对路径,但是System.load方法加载需要文件的绝对路径。
String absoluteName = file.getAbsolutePath();
boolean extracted = false;
try {
if (file.exists()) {
@ -115,7 +160,7 @@ class LibraryLoader {
os.close();
is.close();
chmod("755", fileName);
if (load(fileName, message)) {
if (load(absoluteName, message)) {
return true;
}
}
@ -140,7 +185,7 @@ class LibraryLoader {
}
static void chmod(final String permision, final String path) {
if (isWindows()) {
if (PlatformDetector.OS.isWindows()) {
return;
}
try {
@ -148,69 +193,4 @@ class LibraryLoader {
} catch (Throwable e) {
}
}
static String getOsName() {
return System.getProperty("os.name") + System.getProperty("java.specification.vendor");
}
static boolean isWindows() {
return getOsName().startsWith("Windows");
}
static boolean isMac() {
return getOsName().startsWith("Mac");
}
static boolean isLinux() {
return getOsName().startsWith("Linux");
}
static boolean isNativeClient() {
return getOsName().startsWith("nacl");
}
static boolean isAndroid() {
return getOsName().contains("Android");
}
static String getArchSuffix() {
String arch = System.getProperty("os.arch");
if (arch.equals("i686")) {
return "x86";
} else if (arch.equals("amd64")) {
return "x86_64";
} else if (arch.equals("nacl")) {
return "armv7l";
} else if (arch.equals("aarch64")) {
return "armv7l";
}
return arch;
}
static String getOSFileExtension() {
if (isWindows()) {
return "dll";
} else if (isMac()) {
return "dylib";
} else if (isLinux()) {
return "so";
} else if (isNativeClient()) {
return "so";
}
throw new UnsatisfiedLinkError("Unsupported platform: " + getOsName());
}
static String getOS() {
if (isWindows()) {
return "win32";
} else if (isMac()) {
return "macosx";
} else if (isLinux() && !isAndroid()) {
return "linux";
} else if (isAndroid()) {
return "android";
}
throw new UnsatisfiedLinkError("Unsupported platform: " + getOsName());
}
}

36
fine-j2v8/src/com/eclipsesource/v8/NodeJS.java

@ -29,6 +29,9 @@ public class NodeJS {
private static final String STARTUP_CALLBACK = "__run";
private static final String STARTUP_SCRIPT = "global." + STARTUP_CALLBACK + "(require, exports, module, __filename, __dirname);";
private static final String STARTUP_SCRIPT_NAME = "startup";
private static final String VERSIONS = "versions";
private static final String NODE = "node";
private String nodeVersion = null;
private V8 v8;
private V8Function require;
@ -45,6 +48,29 @@ public class NodeJS {
return createNodeJS(null);
}
/**
* Returns the version of Node.js that is runtime is built against.
* This uses process.versions.node to get the version.
*
* @return The version of Node.js.
*/
public String getNodeVersion() {
if (nodeVersion != null) {
return nodeVersion;
}
V8Object process = null;
V8Object versions = null;
try {
process = v8.getObject(PROCESS);
versions = process.getObject(VERSIONS);
nodeVersion = versions.getString(NODE);
} finally {
safeRelease(process);
safeRelease(versions);
}
return nodeVersion;
}
/**
* Creates a NodeJS runtime and executes a JS Script
*
@ -65,7 +91,7 @@ public class NodeJS {
try {
node.init(require.twin());
} finally {
require.release();
require.close();
}
}
}, STARTUP_CALLBACK);
@ -111,10 +137,10 @@ public class NodeJS {
public void release() {
v8.checkThread();
if (!require.isReleased()) {
require.release();
require.close();
}
if (!v8.isReleased()) {
v8.release();
v8.close();
}
}
@ -142,7 +168,7 @@ public class NodeJS {
requireParams.push(file.getAbsolutePath());
return (V8Object) require.call(null, requireParams);
} finally {
requireParams.release();
requireParams.close();
}
}
@ -179,7 +205,7 @@ public class NodeJS {
requireParams.push(file.getAbsolutePath());
return require.call(null, requireParams);
} finally {
requireParams.release();
requireParams.close();
}
}
});

12
fine-j2v8/src/com/eclipsesource/v8/Platform.java

@ -0,0 +1,12 @@
package com.eclipsesource.v8;
public class Platform {
public static final String ANDROID = "android";
public static final String LINUX = "linux";
public static final String MACOSX = "macosx";
public static final String WINDOWS = "windows";
public static final String NATIVE_CLIENT = "nacl";
public static final String UNKNOWN = "unknown";
}

316
fine-j2v8/src/com/eclipsesource/v8/PlatformDetector.java

@ -0,0 +1,316 @@
/*******************************************************************************
* Copyright (c) 2017 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Trustin Lee - original OS/Arch/Vendor detection code (see: https://github.com/trustin/os-maven-plugin)
* Wolfgang Steiner - initial API and implementation
*
* Copyright 2014 Trustin Heuiseung Lee.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.eclipsesource.v8;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Locale;
public class PlatformDetector {
public static class Arch {
public static String getName() {
final String archProperty = System.getProperty("os.arch");
final String archName = normalizeArch(archProperty);
if (archName.equals(Platform.UNKNOWN)) {
throw new UnsatisfiedLinkError("Unsupported arch: " + archProperty);
}
return archName;
}
}
public static class OS {
public static String getName() {
final String osProperty = System.getProperty("os.name");
final String osName = normalizeOs(osProperty);
final String vendorProperty = System.getProperty("java.specification.vendor");
final String vendorName = normalize(vendorProperty);
// special handling for android
if (vendorName.contains("android") || osName.contains("android")) {
return Platform.ANDROID;
}
if (osName.equals(Platform.UNKNOWN)) {
throw new UnsatisfiedLinkError("Unsupported platform/vendor: " + osProperty + " / " + vendorProperty);
}
return osName;
}
public static boolean isWindows() {
return getName().equals(Platform.WINDOWS);
}
public static boolean isMac() {
return getName().equals(Platform.MACOSX);
}
public static boolean isLinux() {
return getName().equals(Platform.LINUX);
}
public static boolean isNativeClient() {
return getName().equals(Platform.NATIVE_CLIENT);
}
public static boolean isAndroid() {
return getName().equals(Platform.ANDROID);
}
public static String getLibFileExtension() {
if (isWindows()) {
return "dll";
}
if (isMac()) {
return "dylib";
}
if (isLinux()
|| isAndroid()
|| isNativeClient()) {
return "so";
}
throw new UnsatisfiedLinkError("Unsupported platform library-extension for: " + getName());
}
}
public static class Vendor {
private static final String[] LINUX_OS_RELEASE_FILES = {"/etc/os-release", "/usr/lib/os-release"};
private static final String REDHAT_RELEASE_FILE = "/etc/redhat-release";
private static final String LINUX_ID_PREFIX = "ID=";
public static String getName() {
if (OS.isWindows()) {
return "microsoft";
}
if (OS.isMac()) {
return "apple";
}
if (OS.isLinux()) {
return getLinuxOsReleaseId();
}
if (OS.isAndroid()) {
return "google";
}
throw new UnsatisfiedLinkError("Unsupported vendor: " + getName());
}
private static String getLinuxOsReleaseId() {
// First, look for the os-release file.
for (String osReleaseFileName : LINUX_OS_RELEASE_FILES) {
File file = new File(osReleaseFileName);
if (file.exists()) {
return parseLinuxOsReleaseFile(file);
}
}
// Older versions of redhat don't have /etc/os-release. In this case, try
// parsing this file.
File file = new File(REDHAT_RELEASE_FILE);
if (file.exists()) {
return parseLinuxRedhatReleaseFile(file);
}
throw new UnsatisfiedLinkError("Unsupported linux vendor: " + getName());
}
private static String parseLinuxOsReleaseFile(final File file) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
String id = null;
String line;
while((line = reader.readLine()) != null) {
// Parse the ID line.
if (line.startsWith(LINUX_ID_PREFIX)) {
// Set the ID for this version.
id = normalizeOsReleaseValue(line.substring(LINUX_ID_PREFIX.length()));
break;
}
}
return id;
} catch (IOException ignored) {
// Just absorb. Don't treat failure to read /etc/os-release as an error.
} finally {
closeQuietly(reader);
}
return null;
}
private static String parseLinuxRedhatReleaseFile(final File file) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
// There is only a single line in this file.
String line = reader.readLine();
if (line != null) {
line = line.toLowerCase(Locale.US);
String id;
if (line.contains("centos")) {
id = "centos";
} else if (line.contains("fedora")) {
id = "fedora";
} else if (line.contains("red hat enterprise linux")) {
id = "rhel";
} else {
// Other variants are not currently supported.
return null;
}
return id;
}
} catch (IOException ignored) {
// Just absorb. Don't treat failure to read /etc/os-release as an error.
} finally {
closeQuietly(reader);
}
return null;
}
private static void closeQuietly(final Closeable obj) {
try {
if (obj != null) {
obj.close();
}
} catch (IOException ignored) {
// Ignore.
}
}
}
private static String normalizeOsReleaseValue(final String value) {
// Remove any quotes from the string.
return value.trim().replace("\"", "");
}
private static String normalizeOs(String value) {
value = normalize(value);
if (value.startsWith("aix")) {
return "aix";
}
if (value.startsWith("hpux")) {
return "hpux";
}
if (value.startsWith("os400")) {
// Avoid the names such as os4000
if ((value.length() <= 5) || !Character.isDigit(value.charAt(5))) {
return "os400";
}
}
if (value.startsWith("android")) {
return Platform.ANDROID;
}
if (value.startsWith("linux")) {
return Platform.LINUX;
}
if (value.startsWith("nacl")) {
return Platform.NATIVE_CLIENT;
}
if (value.startsWith("macosx") || value.startsWith("osx")) {
return Platform.MACOSX;
}
if (value.startsWith("freebsd")) {
return "freebsd";
}
if (value.startsWith("openbsd")) {
return "openbsd";
}
if (value.startsWith("netbsd")) {
return "netbsd";
}
if (value.startsWith("solaris") || value.startsWith("sunos")) {
return "sunos";
}
if (value.startsWith("windows")) {
return Platform.WINDOWS;
}
return Platform.UNKNOWN;
}
private static String normalizeArch(String value) {
value = normalize(value);
if (value.matches("^(x8664|amd64|ia32e|em64t|x64)$")) {
return "x86_64";
}
if (value.matches("^(x8632|x86|i[3-6]86|ia32|x32)$")) {
return "x86_32";
}
if (value.matches("^(ia64|itanium64)$")) {
return "itanium_64";
}
if (value.matches("^(sparc|sparc32)$")) {
return "sparc_32";
}
if (value.matches("^(sparcv9|sparc64)$")) {
return "sparc_64";
}
if (value.matches("^(arm|arm32)$")) {
return "arm_32";
}
if ("aarch64".equals(value)) {
return "aarch_64";
}
if (value.matches("^(ppc|ppc32)$")) {
return "ppc_32";
}
if ("ppc64".equals(value)) {
return "ppc_64";
}
if ("ppc64le".equals(value)) {
return "ppcle_64";
}
if ("s390".equals(value)) {
return "s390_32";
}
if ("s390x".equals(value)) {
return "s390_64";
}
return Platform.UNKNOWN;
}
private static String normalize(final String value) {
if (value == null) {
return "";
}
return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
}
}

10
fine-j2v8/src/com/eclipsesource/v8/Releasable.java

@ -10,15 +10,21 @@
******************************************************************************/
package com.eclipsesource.v8;
import java.io.Closeable;
/**
* An interface used to denote all V8 Classes which can be released.
*/
public interface Releasable {
public interface Releasable extends Closeable {
/**
* Release the underlying resources. Once an object is released
* it typically cannot be used again.
*/
void release();
void close();
/**
* Synonym for {@link #close()}.
*/
void release();
}

208
fine-j2v8/src/com/eclipsesource/v8/V8.java

@ -22,6 +22,7 @@ import java.util.Set;
import com.eclipsesource.v8.utils.V8Executor;
import com.eclipsesource.v8.utils.V8Map;
import com.eclipsesource.v8.utils.V8Runnable;
/**
* An isolated V8Runtime. All JavaScript execution must exist
@ -42,7 +43,9 @@ public class V8 extends V8Object {
private volatile static int runtimeCounter = 0;
private static String v8Flags = null;
private static boolean initialized = false;
protected Map<Long, V8Value> v8WeakReferences = new HashMap<Long, V8Value>();
private Map<String, Object> data = null;
private final V8Locker locker;
private long objectReferences = 0;
private long v8RuntimePtr = 0;
@ -51,11 +54,12 @@ public class V8 extends V8Object {
private boolean forceTerminateExecutors = false;
private Map<Long, MethodDescriptor> functionRegistry = new HashMap<Long, MethodDescriptor>();
private LinkedList<ReferenceHandler> referenceHandlers = new LinkedList<ReferenceHandler>();
private LinkedList<V8Runnable> releaseHandlers = new LinkedList<V8Runnable>();
private static boolean nativeLibraryLoaded = false;
private static Error nativeLoadError = null;
private static Exception nativeLoadException = null;
private static V8Value undefined = new Undefined();
private static V8Value undefined = new V8Object.Undefined();
private static Object invalid = new Object();
private class MethodDescriptor {
@ -167,6 +171,16 @@ public class V8 extends V8Object {
referenceHandlers.add(0, handler);
}
/**
* Adds a handler that will be called when the runtime is being released.
* The runtime will still be available when the handler is executed.
*
* @param handler The handler to invoke when the runtime, is being released
*/
public void addReleaseHandler(final V8Runnable handler) {
releaseHandlers.add(handler);
}
/**
* Removes an existing ReferenceHandler from the collection of reference handlers.
* If the ReferenceHandler does not exist in the collection, it is ignored.
@ -177,6 +191,50 @@ public class V8 extends V8Object {
referenceHandlers.remove(handler);
}
/**
* Removes an existing release handler from the collection of release handlers.
* If the release handler does not exist in the collection, it is ignored.
*
* @param handler The handler to remove
*/
public void removeReleaseHandler(final V8Runnable handler) {
releaseHandlers.remove(handler);
}
/**
* Associates an arbitrary object with this runtime.
*
* @param key The key used to reference this object
* @param value The object to associate with this runtime
*/
public synchronized void setData(final String key, final Object value) {
if (data == null) {
data = new HashMap<String, Object>();
}
data.put(key, value);
}
/**
* Returns the data object associated with this runtime, null if no object
* has been associated.
*
* @param key The key used to reference this object
*
* @return The data object associated with this runtime, or null.
*/
public Object getData(final String key) {
if (data == null) {
return null;
}
return data.get(key);
}
private void notifyReleaseHandlers(final V8 runtime) {
for (V8Runnable handler : releaseHandlers) {
handler.run(runtime);
}
}
private void notifyReferenceCreated(final V8Value object) {
for (ReferenceHandler referenceHandler : referenceHandlers) {
referenceHandler.v8HandleCreated(object);
@ -191,12 +249,16 @@ public class V8 extends V8Object {
private static void checkNativeLibraryLoaded() {
if (!nativeLibraryLoaded) {
String vendorName = LibraryLoader.computeLibraryShortName(true);
String baseName = LibraryLoader.computeLibraryShortName(false);
String message = "J2V8 native library not loaded (" + baseName + "/" + vendorName + ")";
if (nativeLoadError != null) {
throw new IllegalStateException("J2V8 native library not loaded", nativeLoadError);
throw new IllegalStateException(message, nativeLoadError);
} else if (nativeLoadException != null) {
throw new IllegalStateException("J2V8 native library not loaded", nativeLoadException);
throw new IllegalStateException(message, nativeLoadException);
} else {
throw new IllegalStateException("J2V8 native library not loaded");
throw new IllegalStateException(message);
}
}
}
@ -208,9 +270,9 @@ public class V8 extends V8Object {
protected V8(final String globalAlias) {
super(null);
released = false;
locker = new V8Locker();
checkThread();
v8RuntimePtr = _createIsolate(globalAlias);
locker = new V8Locker(this);
checkThread();
objectHandle = _getGlobalObject(v8RuntimePtr);
}
@ -238,7 +300,7 @@ public class V8 extends V8Object {
* @return The number of Object References on this runtime.
*/
public long getObjectReferenceCount() {
return objectReferences;
return objectReferences - v8WeakReferences.size();
}
protected long getV8RuntimePtr() {
@ -254,11 +316,32 @@ public class V8 extends V8Object {
return _getVersion();
}
/**
* Returns the revision ID of this version as specified
* by the source code management system. Currently we use
* Git, so this will return the commit ID for this revision.
*
* @return The revision ID of this version of J2V8
*/
public static String getSCMRevision() {
return "Unknown revision ID";
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#close()
*/
@Override
public void close() {
release(true);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#release()
*/
@Override
@Deprecated
public void release() {
release(true);
}
@ -286,6 +369,9 @@ public class V8 extends V8Object {
return;
}
checkThread();
try {
notifyReleaseHandlers(this);
} finally {
releaseResources();
shutdownExecutors(forceTerminateExecutors);
if (executors != null) {
@ -298,8 +384,9 @@ public class V8 extends V8Object {
_releaseRuntime(v8RuntimePtr);
v8RuntimePtr = 0L;
released = true;
if (reportMemoryLeaks && (objectReferences > 0)) {
throw new IllegalStateException(objectReferences + " Object(s) still exist in runtime");
if (reportMemoryLeaks && (getObjectReferenceCount() > 0)) {
throw new IllegalStateException(getObjectReferenceCount() + " Object(s) still exist in runtime");
}
}
}
@ -672,6 +759,28 @@ public class V8 extends V8Object {
return _getBuildID();
}
/**
* Indicates to V8 that the system is low on memory.
* V8 may use this to attempt to recover space by running
* the garbage collector.
*/
public void lowMemoryNotification() {
checkThread();
lowMemoryNotification(getV8RuntimePtr());
}
void checkRuntime(final V8Value value) {
if ((value == null) || value.isUndefined()) {
return;
}
V8 runtime = value.getRuntime();
if ((runtime == null) ||
runtime.isReleased() ||
(runtime != this)) {
throw new Error("Invalid target runtime");
}
}
void checkThread() {
locker.checkThread();
if (isReleased()) {
@ -722,7 +831,7 @@ public class V8 extends V8Object {
private Object getDefaultValue(final Class<?> type) {
if (type.equals(V8Object.class)) {
return new Undefined();
return new V8Object.Undefined();
} else if (type.equals(V8Array.class)) {
return new V8Array.Undefined();
}
@ -733,6 +842,20 @@ public class V8 extends V8Object {
functionRegistry.remove(methodID);
}
protected void weakReferenceReleased(final long objectID) {
V8Value v8Value = v8WeakReferences.get(objectID);
if (v8Value != null) {
v8WeakReferences.remove(objectID);
try {
v8Value.close();
} catch (Exception e) {
// Swallow these exceptions. The V8 GC is running, and
// if we return to V8 with Java exception on our stack,
// we will be in a world of hurt.
}
}
}
protected Object callObjectJavaMethod(final long methodID, final V8Object receiver, final V8Array parameters) throws Throwable {
MethodDescriptor methodDescriptor = functionRegistry.get(methodID);
if (methodDescriptor.callback != null) {
@ -810,13 +933,13 @@ public class V8 extends V8Object {
Object[] varArgs = (Object[]) args[args.length - 1];
for (Object object : varArgs) {
if (object instanceof V8Value) {
((V8Value) object).release();
((V8Value) object).close();
}
}
}
for (Object arg : args) {
if (arg instanceof V8Value) {
((V8Value) arg).release();
((V8Value) arg).close();
}
}
}
@ -916,6 +1039,22 @@ public class V8 extends V8Object {
return _initNewV8Object(v8RuntimePtr);
}
protected long initEmptyContainer(final long v8RuntimePtr) {
return _initEmptyContainer(v8RuntimePtr);
}
protected void acquireLock(final long v8RuntimePtr) {
_acquireLock(v8RuntimePtr);
}
protected void releaseLock(final long v8RuntimePtr) {
_releaseLock(v8RuntimePtr);
}
protected void lowMemoryNotification(final long v8RuntimePtr) {
_lowMemoryNotification(v8RuntimePtr);
}
protected void createTwin(final long v8RuntimePtr, final long objectHandle, final long twinHandle) {
_createTwin(v8RuntimePtr, objectHandle, twinHandle);
}
@ -944,6 +1083,18 @@ public class V8 extends V8Object {
_executeVoidScript(v8RuntimePtr, script, scriptName, lineNumber);
}
protected void setWeak(final long v8RuntimePtr, final long objectHandle) {
_setWeak(v8RuntimePtr, objectHandle);
}
protected void clearWeak(final long v8RuntimePtr, final long objectHandle) {
_clearWeak(v8RuntimePtr, objectHandle);
}
protected boolean isWeak(final long v8RuntimePtr, final long objectHandle) {
return _isWeak(v8RuntimePtr, objectHandle);
}
protected void release(final long v8RuntimePtr, final long objectHandle) {
_release(v8RuntimePtr, objectHandle);
}
@ -1170,6 +1321,10 @@ public class V8 extends V8Object {
_addArrayNullItem(v8RuntimePtr, arrayHandle);
}
protected int getType(final long v8RuntimePtr, final long objectHandle) {
return _getType(v8RuntimePtr, objectHandle);
}
protected int getType(final long v8RuntimePtr, final long objectHandle, final String key) {
return _getType(v8RuntimePtr, objectHandle, key);
}
@ -1240,6 +1395,14 @@ public class V8 extends V8Object {
private native long _initNewV8Object(long v8RuntimePtr);
private native long _initEmptyContainer(long v8RuntimePtr);
private native void _acquireLock(long v8RuntimePtr);
private native void _releaseLock(long v8RuntimePtr);
private native void _lowMemoryNotification(long v8RuntimePtr);
private native void _createTwin(long v8RuntimePtr, long objectHandle, long twinHandle);
private native void _releaseRuntime(long v8RuntimePtr);
@ -1356,6 +1519,8 @@ public class V8 extends V8Object {
private native void _setPrototype(long v8RuntimePtr, long objectHandle, long prototypeHandle);
private native int _getType(long v8RuntimePtr, long objectHandle);
private native int _getType(long v8RuntimePtr, long objectHandle, final int index, final int length);
private native double[] _arrayGetDoubles(final long v8RuntimePtr, final long objectHandle, final int index, final int length);
@ -1400,6 +1565,12 @@ public class V8 extends V8Object {
private native long _initNewV8UInt8ClampedArray(long runtimePtr, long bufferHandle, int offset, int size);
private native void _setWeak(long runtimePtr, long objectHandle);
private native void _clearWeak(long runtimePtr, long objectHandle);
private native boolean _isWeak(long runtimePtr, long objectHandle);
private native ByteBuffer _createV8ArrayBufferBackingStore(final long v8RuntimePtr, final long objectHandle, final int capacity);
private native static String _getVersion();
@ -1418,6 +1589,19 @@ public class V8 extends V8Object {
private native static boolean _isRunning(final long v8RuntimePtr);
private native static boolean _isNodeCompatible();
public static boolean isNodeCompatible() {
if (!nativeLibraryLoaded) {
synchronized (lock) {
if (!nativeLibraryLoaded) {
load(null);
}
}
}
return _isNodeCompatible();
}
void addObjRef(final V8Value reference) {
objectReferences++;
if (!referenceHandlers.isEmpty()) {

62
fine-j2v8/src/com/eclipsesource/v8/V8Array.java

@ -51,6 +51,18 @@ public class V8Array extends V8Object {
return (V8Array) super.twin();
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Object#toString()
*/
@Override
public String toString() {
if (released || v8.isReleased()) {
return "[Array released]";
}
return super.toString();
}
@Override
protected void initialize(final long runtimePtr, final Object data) {
long handle = v8.initNewV8Array(runtimePtr);
@ -521,6 +533,7 @@ public class V8Array extends V8Object {
public V8Array push(final V8Value value) {
v8.checkThread();
checkReleased();
v8.checkRuntime(value);
if (value == null) {
v8.addArrayNullItem(v8.getV8RuntimePtr(), getHandle());
} else if (value.equals(V8.getUndefined())) {
@ -531,6 +544,46 @@ public class V8Array extends V8Object {
return this;
}
/**
* Pushes a Object to the next available spot in the Array. In
* particular, this[length] = value;
*
* @param value The value to push to the array.
*
* @return The receiver.
*/
public V8Array push(final Object value) {
v8.checkThread();
checkReleased();
if (value instanceof V8Value) {
v8.checkRuntime((V8Value) value);
}
if (value == null) {
v8.addArrayNullItem(v8.getV8RuntimePtr(), getHandle());
} else if (value.equals(V8.getUndefined())) {
v8.addArrayUndefinedItem(v8.getV8RuntimePtr(), getHandle());
} else {
if (value instanceof Double) {
v8.addArrayDoubleItem(v8.getV8RuntimePtr(), getHandle(), (Double) value);
} else if (value instanceof Integer) {
v8.addArrayIntItem(v8.getV8RuntimePtr(), getHandle(), (Integer) value);
} else if (value instanceof Float) {
v8.addArrayDoubleItem(v8.getV8RuntimePtr(), getHandle(), ((Float) value).doubleValue());
} else if (value instanceof Number) {
v8.addArrayDoubleItem(v8.getV8RuntimePtr(), getHandle(), ((Number) value).doubleValue());
} else if (value instanceof Boolean) {
v8.addArrayBooleanItem(v8.getV8RuntimePtr(), getHandle(), (Boolean) value);
} else if (value instanceof String) {
v8.addArrayStringItem(v8.getV8RuntimePtr(), getHandle(), (String) value);
} else if (value instanceof V8Value) {
v8.addArrayObjectItem(v8.getV8RuntimePtr(), getHandle(), ((V8Value) value).getHandle());
} else {
throw new IllegalArgumentException();
}
}
return this;
}
/**
* Pushes null to the next available spot in the Array. In
* particular, this[length] = null;
@ -580,11 +633,20 @@ public class V8Array extends V8Object {
return false;
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#close()
*/
@Override
public void close() {
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#release()
*/
@Override
@Deprecated
public void release() {
}

401
fine-j2v8/src/com/eclipsesource/v8/V8ArrayBuffer.java

@ -25,7 +25,7 @@ import java.nio.ByteOrder;
*/
public class V8ArrayBuffer extends V8Value {
private ByteBuffer byteBuffer;
ByteBuffer byteBuffer;
/**
* Creates a new V8ArrayBuffer on a given V8Runtime with a
@ -41,17 +41,11 @@ public class V8ArrayBuffer extends V8Value {
byteBuffer.order(ByteOrder.nativeOrder());
}
/**
* Creates a new V8ArrayBuffer with the provided ByteBuffer as the backing store.
* The ByteBuffer must be allocated as a DirectBuffer. If the ByteBuffer is not
* a DirectBuffer an IllegalArgumentException will be thrown.
*
* @param v8 The runtime on which to create the ArrayBuffer
* @param byteBuffer The ByteBuffer to use as the backing store. The ByteBuffer must
* be allocated as a DirectBuffer.
*/
public V8ArrayBuffer(final V8 v8, final ByteBuffer byteBuffer) {
public V8ArrayBuffer(final V8 v8, ByteBuffer byteBuffer) {
super(v8);
if (byteBuffer == null) {
byteBuffer = ByteBuffer.allocateDirect(0);
}
if (!byteBuffer.isDirect()) {
throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer");
}
@ -86,18 +80,393 @@ public class V8ArrayBuffer extends V8Value {
*/
@Override
public V8ArrayBuffer twin() {
v8.checkThread();
checkReleased();
return (V8ArrayBuffer) super.twin();
}
/**
* Returns the backing store used for this ArrayBuffer.
* Returns the buffers limit
*
* @return the buffers limit
*/
public int limit() {
v8.checkThread();
checkReleased();
return byteBuffer.limit();
}
/**
* Returns the buffers capacity
*
* @return The backing store used for this ArrayBuffer.
* @return the buffers capacity
*/
public ByteBuffer getBackingStore() {
v8.checkReleased();
public final int capacity() {
v8.checkThread();
checkReleased();
return byteBuffer.capacity();
}
/**
*
* @return
*/
public final int position() {
v8.checkThread();
checkReleased();
return byteBuffer.position();
}
public final V8ArrayBuffer position(final int newPosition) {
v8.checkThread();
checkReleased();
byteBuffer.position(newPosition);
return this;
}
public final V8ArrayBuffer limit(final int newLimit) {
v8.checkThread();
checkReleased();
byteBuffer.limit(newLimit);
return this;
}
public final V8ArrayBuffer mark() {
v8.checkThread();
checkReleased();
byteBuffer.mark();
return this;
}
public final V8ArrayBuffer reset() {
v8.checkThread();
checkReleased();
byteBuffer.reset();
return this;
}
public final V8ArrayBuffer clear() {
v8.checkThread();
checkReleased();
byteBuffer.clear();
return this;
}
public final V8ArrayBuffer flip() {
v8.checkThread();
checkReleased();
byteBuffer.flip();
return this;
}
public final V8ArrayBuffer rewind() {
v8.checkThread();
checkReleased();
byteBuffer.rewind();
return this;
}
public final int remaining() {
v8.checkThread();
checkReleased();
return byteBuffer.remaining();
}
public final boolean hasRemaining() {
v8.checkThread();
checkReleased();
return byteBuffer.hasRemaining();
}
public boolean isReadOnly() {
v8.checkThread();
checkReleased();
return byteBuffer.isReadOnly();
}
public byte get() {
v8.checkThread();
checkReleased();
return byteBuffer.get();
}
public V8ArrayBuffer put(final byte b) {
v8.checkThread();
checkReleased();
byteBuffer.put(b);
return this;
}
public byte get(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.get(index);
}
public V8ArrayBuffer put(final int index, final byte b) {
v8.checkThread();
checkReleased();
byteBuffer.put(index, b);
return this;
}
public V8ArrayBuffer get(final byte[] dst, final int offset, final int length) {
v8.checkThread();
checkReleased();
byteBuffer.get(dst, offset, length);
return this;
}
public V8ArrayBuffer get(final byte[] dst) {
v8.checkThread();
checkReleased();
byteBuffer.get(dst);
return this;
}
public V8ArrayBuffer put(final ByteBuffer src) {
v8.checkThread();
checkReleased();
byteBuffer.put(src);
return this;
}
public V8ArrayBuffer put(final byte[] src, final int offset, final int length) {
v8.checkThread();
checkReleased();
byteBuffer.put(src, offset, length);
return this;
}
public final V8ArrayBuffer put(final byte[] src) {
v8.checkThread();
checkReleased();
byteBuffer.put(src);
return this;
}
public final boolean hasArray() {
v8.checkThread();
checkReleased();
return byteBuffer.hasArray();
}
public final byte[] array() {
v8.checkThread();
checkReleased();
return byteBuffer.array();
}
public final int arrayOffset() {
v8.checkThread();
checkReleased();
return byteBuffer.arrayOffset();
}
public V8ArrayBuffer compact() {
v8.checkThread();
checkReleased();
byteBuffer.compact();
return this;
}
public boolean isDirect() {
v8.checkThread();
checkReleased();
return byteBuffer.isDirect();
}
public final ByteOrder order() {
v8.checkThread();
checkReleased();
return byteBuffer.order();
}
public final V8ArrayBuffer order(final ByteOrder bo) {
v8.checkThread();
checkReleased();
byteBuffer.order(bo);
return this;
}
public char getChar() {
v8.checkThread();
checkReleased();
return byteBuffer.getChar();
}
public V8ArrayBuffer putChar(final char value) {
v8.checkThread();
checkReleased();
byteBuffer.putChar(value);
return this;
}
public char getChar(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getChar(index);
}
public V8ArrayBuffer putChar(final int index, final char value) {
v8.checkThread();
checkReleased();
byteBuffer.putChar(index, value);
return this;
}
public short getShort() {
v8.checkThread();
checkReleased();
return byteBuffer.getShort();
}
public V8ArrayBuffer putShort(final short value) {
v8.checkThread();
checkReleased();
byteBuffer.putShort(value);
return this;
}
public short getShort(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getShort(index);
}
public V8ArrayBuffer putShort(final int index, final short value) {
v8.checkThread();
checkReleased();
byteBuffer.putShort(index, value);
return this;
}
public int getInt() {
v8.checkThread();
checkReleased();
return byteBuffer.getInt();
}
public V8ArrayBuffer putInt(final int value) {
v8.checkThread();
checkReleased();
byteBuffer.putInt(value);
return this;
}
public int getInt(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getInt(index);
}
public V8ArrayBuffer putInt(final int index, final int value) {
v8.checkThread();
checkReleased();
byteBuffer.asIntBuffer().put(index, value);
return this;
}
public long getLong() {
v8.checkThread();
checkReleased();
return byteBuffer.getLong();
}
public V8ArrayBuffer putLong(final long value) {
v8.checkThread();
checkReleased();
byteBuffer.putLong(value);
return this;
}
public long getLong(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getLong(index);
}
public V8ArrayBuffer putLong(final int index, final long value) {
v8.checkThread();
checkReleased();
byteBuffer.putLong(index, value);
return this;
}
public float getFloat() {
v8.checkThread();
checkReleased();
return byteBuffer.getFloat();
}
public V8ArrayBuffer putFloat(final float value) {
v8.checkThread();
checkReleased();
byteBuffer.putFloat(value);
return this;
}
public float getFloat(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getFloat(index);
}
public V8ArrayBuffer putFloat(final int index, final float value) {
v8.checkThread();
checkReleased();
byteBuffer.putFloat(index, value);
return this;
}
public double getDouble() {
v8.checkThread();
checkReleased();
return byteBuffer.getDouble();
}
public V8ArrayBuffer putDouble(final double value) {
v8.checkThread();
checkReleased();
byteBuffer.putDouble(value);
return this;
}
public double getDouble(final int index) {
v8.checkThread();
checkReleased();
return byteBuffer.getDouble(index);
}
public V8ArrayBuffer putDouble(final int index, final double value) {
v8.checkThread();
checkReleased();
byteBuffer.putDouble(index, value);
return this;
}
public int floatLimit() {
v8.checkThread();
checkReleased();
return byteBuffer.asFloatBuffer().limit();
}
public int intLimit() {
v8.checkThread();
checkReleased();
return byteBuffer.asIntBuffer().limit();
}
public int shortLimit() {
v8.checkThread();
checkReleased();
return byteBuffer.asShortBuffer().limit();
}
public int doubleLimit() {
v8.checkThread();
return byteBuffer;
checkReleased();
return byteBuffer.asDoubleBuffer().limit();
}
}

15
fine-j2v8/src/com/eclipsesource/v8/V8Function.java

@ -38,6 +38,18 @@ public class V8Function extends V8Object {
return new V8Function(v8);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Object#toString()
*/
@Override
public String toString() {
if (released || v8.isReleased()) {
return "[Function released]";
}
return super.toString();
}
@Override
protected void initialize(final long runtimePtr, final Object data) {
if (data == null) {
@ -71,9 +83,12 @@ public class V8Function extends V8Object {
*
* @return The result of JavaScript function.
*/
@SuppressWarnings("resource")
public Object call(V8Object receiver, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(receiver);
v8.checkRuntime(parameters);
receiver = receiver != null ? receiver : v8;
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
long receiverHandle = receiver.isUndefined() ? v8.getHandle() : receiver.getHandle();

53
fine-j2v8/src/com/eclipsesource/v8/V8Locker.java

@ -19,31 +19,71 @@ package com.eclipsesource.v8;
public class V8Locker {
private Thread thread = null;
private boolean released = false;
private V8 runtime;
V8Locker() {
V8Locker(final V8 runtime) {
this.runtime = runtime;
acquire();
}
/**
* Returns the current thread associated with locker.
*
* @return The currently locked thread.
*/
public Thread getThread() {
return thread;
}
/**
* Acquire the lock if it's currently not acquired by another
* thread. If it's current held by another thread, an
* thread. If it's currently held by another thread, an
* Error will be thrown.
*/
public synchronized void acquire() {
if ((thread != null) && (thread != Thread.currentThread())) {
throw new Error("Invalid V8 thread access");
throw new Error("Invalid V8 thread access: current thread is " + Thread.currentThread() + " while the locker has thread " + thread);
} else if ((thread == Thread.currentThread())) {
return;
}
runtime.acquireLock(runtime.getV8RuntimePtr());
thread = Thread.currentThread();
released = false;
}
/**
* Acquire the lock if it's currently not acquired by another
* thread. If it's currently held by another thread, tryAcquire
* will return false, otherwise true is returned.
*
* @return Returns true if the lock was acquired, false otherwise.
*/
public synchronized boolean tryAcquire() {
if ((thread != null) && (thread != Thread.currentThread())) {
return false;
} else if (thread == Thread.currentThread()) {
return true;
}
runtime.acquireLock(runtime.getV8RuntimePtr());
thread = Thread.currentThread();
released = false;
return true;
}
/**
* Release the lock if it's currently held by the calling thread.
* If the current thread does not hold the lock, and error will be
* thrown.
* thrown. If no thread holds the lock then nothing will happen.
*/
public synchronized void release() {
if ((released && (thread == null)) || runtime.isReleased()) {
return;
}
checkThread();
runtime.releaseLock(runtime.getV8RuntimePtr());
thread = null;
released = true;
}
/**
@ -52,8 +92,11 @@ public class V8Locker {
* is thrown.
*/
public void checkThread() {
if(released && (thread == null)){
throw new Error("Invalid V8 thread access: the locker has been released!");
}
if ((thread != Thread.currentThread())) {
throw new Error("Invalid V8 thread access");
throw new Error("Invalid V8 thread access: current thread is " + Thread.currentThread() + " while the locker has thread " + thread);
}
}

45
fine-j2v8/src/com/eclipsesource/v8/V8Object.java

@ -73,6 +73,7 @@ public class V8Object extends V8Value {
public boolean contains(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.contains(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -100,6 +101,7 @@ public class V8Object extends V8Value {
public int getType(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.getType(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -115,6 +117,7 @@ public class V8Object extends V8Value {
public Object get(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.get(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, key);
}
@ -131,6 +134,7 @@ public class V8Object extends V8Value {
public int getInteger(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.getInteger(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -147,6 +151,7 @@ public class V8Object extends V8Value {
public boolean getBoolean(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.getBoolean(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -163,6 +168,7 @@ public class V8Object extends V8Value {
public double getDouble(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.getDouble(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -179,6 +185,7 @@ public class V8Object extends V8Value {
public String getString(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
return v8.getString(v8.getV8RuntimePtr(), objectHandle, key);
}
@ -195,6 +202,7 @@ public class V8Object extends V8Value {
public V8Array getArray(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
Object result = v8.get(v8.getV8RuntimePtr(), V8_ARRAY, objectHandle, key);
if ((result == null) || (result instanceof V8Array)) {
return (V8Array) result;
@ -215,6 +223,7 @@ public class V8Object extends V8Value {
public V8Object getObject(final String key) {
v8.checkThread();
checkReleased();
checkKey(key);
Object result = v8.get(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, key);
if ((result == null) || (result instanceof V8Object)) {
return (V8Object) result;
@ -236,6 +245,7 @@ public class V8Object extends V8Value {
public int executeIntegerFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
return v8.executeIntegerFunction(v8.getV8RuntimePtr(), getHandle(), name, parametersHandle);
}
@ -254,6 +264,7 @@ public class V8Object extends V8Value {
public double executeDoubleFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
return v8.executeDoubleFunction(v8.getV8RuntimePtr(), getHandle(), name, parametersHandle);
}
@ -272,6 +283,7 @@ public class V8Object extends V8Value {
public String executeStringFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
return v8.executeStringFunction(v8.getV8RuntimePtr(), getHandle(), name, parametersHandle);
}
@ -290,6 +302,7 @@ public class V8Object extends V8Value {
public boolean executeBooleanFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
return v8.executeBooleanFunction(v8.getV8RuntimePtr(), getHandle(), name, parametersHandle);
}
@ -308,6 +321,7 @@ public class V8Object extends V8Value {
public V8Array executeArrayFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
Object result = v8.executeFunction(v8.getV8RuntimePtr(), V8_ARRAY, objectHandle, name, parametersHandle);
if (result instanceof V8Array) {
@ -330,6 +344,7 @@ public class V8Object extends V8Value {
public V8Object executeObjectFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
Object result = v8.executeFunction(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, name, parametersHandle);
if (result instanceof V8Object) {
@ -350,6 +365,7 @@ public class V8Object extends V8Value {
public Object executeFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
return v8.executeFunction(v8.getV8RuntimePtr(), UNKNOWN, objectHandle, name, parametersHandle);
}
@ -383,15 +399,15 @@ public class V8Object extends V8Value {
} else if (object instanceof V8Value) {
parameterArray.push((V8Value) object);
} else if (object instanceof Integer) {
parameterArray.push((Integer) object);
parameterArray.push(object);
} else if (object instanceof Double) {
parameterArray.push((Double) object);
parameterArray.push(object);
} else if (object instanceof Long) {
parameterArray.push(((Long) object).doubleValue());
} else if (object instanceof Float) {
parameterArray.push(((Float) object).floatValue());
} else if (object instanceof Boolean) {
parameterArray.push((Boolean) object);
parameterArray.push(object);
} else if (object instanceof String) {
parameterArray.push((String) object);
} else {
@ -400,7 +416,7 @@ public class V8Object extends V8Value {
}
return executeFunction(name, parameterArray);
} finally {
parameterArray.release();
parameterArray.close();
}
}
@ -414,6 +430,7 @@ public class V8Object extends V8Value {
public void executeVoidFunction(final String name, final V8Array parameters) {
v8.checkThread();
checkReleased();
v8.checkRuntime(parameters);
long parametersHandle = parameters == null ? 0 : parameters.getHandle();
v8.executeVoidFunction(v8.getV8RuntimePtr(), objectHandle, name, parametersHandle);
}
@ -495,6 +512,7 @@ public class V8Object extends V8Value {
public V8Object add(final String key, final V8Value value) {
v8.checkThread();
checkReleased();
v8.checkRuntime(value);
if (value == null) {
v8.addNull(v8.getV8RuntimePtr(), objectHandle, key);
} else if (value.equals(V8.getUndefined())) {
@ -629,11 +647,19 @@ public class V8Object extends V8Value {
*/
@Override
public String toString() {
if (isReleased() || v8.isReleased()) {
return "[Object released]";
}
v8.checkThread();
checkReleased();
return v8.toString(v8.getV8RuntimePtr(), getHandle());
}
private void checkKey(final String key) {
if (key == null) {
throw new IllegalArgumentException("Key cannot be null");
}
}
static class Undefined extends V8Object {
public Undefined() {
@ -657,10 +683,19 @@ public class V8Object extends V8Value {
return false;
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#close()
*/
@Override
public void close() {
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.V8Value#release()
*/
@Deprecated
@Override
public void release() {
}

62
fine-j2v8/src/com/eclipsesource/v8/V8TypedArray.java

@ -10,8 +10,6 @@
******************************************************************************/
package com.eclipsesource.v8;
import java.nio.ByteBuffer;
/**
* A representation of a JS TypedArray in Java. The typed array is simply a 'view' onto
* a back buffer.
@ -37,6 +35,41 @@ public class V8TypedArray extends V8Array {
super(v8);
}
@Override
protected V8Value createTwin() {
v8.checkThread();
checkReleased();
return new V8TypedArray(v8);
}
@Override
public Object get(final int index) {
v8.checkThread();
checkReleased();
int type = getType();
switch (type) {
case FLOAT_32_ARRAY:
return ((Number) super.get(index)).floatValue();
case FLOAT_64_ARRAY:
return super.get(index);
case INT_32_ARRAY:
return super.get(index);
case INT_16_ARRAY:
return ((Number) super.get(index)).shortValue();
case INT_8_ARRAY:
return ((Number) super.get(index)).byteValue();
case UNSIGNED_INT_16_ARRAY:
return 0xFFFF & (Integer) super.get(index);
case UNSIGNED_INT_32_ARRAY:
return 0x00000000FFFFFFFF & ((Number) super.get(index)).longValue();
case UNSIGNED_INT_8_CLAMPED_ARRAY:
return (short) (0x00FF & ((Number) super.get(index)).byteValue());
case UNSIGNED_INT_8_ARRAY:
return (short) (0x00FF & ((Number) super.get(index)).shortValue());
}
return null;
}
/**
* Provide access to the underlying ByteBuffer used for this TypedArray.
* The V8ArrayBuffer must be released.
@ -47,20 +80,6 @@ public class V8TypedArray extends V8Array {
return (V8ArrayBuffer) get("buffer");
}
/**
* Returns the underlying ByteBuffer used to back this TypedArray.
*
* @return The ByteBuffer used as the backing store for this TypedArray
*/
public ByteBuffer getByteBuffer() {
V8ArrayBuffer buffer = getBuffer();
try {
return buffer.getBackingStore();
} finally {
buffer.release();
}
}
@Override
protected void initialize(final long runtimePtr, final Object data) {
v8.checkThread();
@ -96,7 +115,7 @@ public class V8TypedArray extends V8Array {
case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY:
return v8.initNewV8UInt8ClampedArray(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
default:
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentaion(arrayData.type));
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentation(arrayData.type));
}
}
@ -122,7 +141,7 @@ public class V8TypedArray extends V8Array {
case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY:
return 1;
default:
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentaion(type));
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentation(type));
}
}
@ -136,7 +155,7 @@ public class V8TypedArray extends V8Array {
throw new IllegalStateException("RangeError: Invalid typed array length");
}
int limit = (arrayData.size * getStructureSize(arrayData.type)) + arrayData.offset;
if (limit > arrayData.buffer.getBackingStore().limit()) {
if (limit > arrayData.buffer.limit()) {
throw new IllegalStateException("RangeError: Invalid typed array length");
}
}
@ -147,11 +166,6 @@ public class V8TypedArray extends V8Array {
}
}
@Override
protected V8Value createTwin() {
return new V8TypedArray(v8);
}
private static class V8ArrayData {
private V8ArrayBuffer buffer;
private int offset;

103
fine-j2v8/src/com/eclipsesource/v8/V8Value.java

@ -12,16 +12,16 @@ package com.eclipsesource.v8;
/**
* A base class for all V8 resources. V8 resources must
* be released. The rules for releasing resources is as
* be closed/released. The rules for releasing resources is as
* follows:
*
* 1. If you created it, you must release it, with one exception;
* 1. If you created it, you must close it, with one exception;
* if the object is being passed pack via a return statement,
* the system will release it for you.
*
* 2. If the system created it, you dont need to worry about it,
* with one caveat; if the object was returned to you as a
* result of a method call, you must release it.
* result of a method call, you must close it.
*/
abstract public class V8Value implements Releasable {
@ -83,12 +83,24 @@ abstract public class V8Value implements Releasable {
}
}
/**
* Returns a string representation of the V8 Type.
* @param type Type to return as a string. See constants in V8Value.
* @return The V8Value type as a string.
* @deprecated Use
*/
@Deprecated
public static String getStringRepresentaion(final int type) {
return getStringRepresentation(type);
}
/**
* Returns a string representation of the V8 Type.
* @param type Type to return as a string. See constants in V8Value.
* @return The V8Value type as a string.
*/
public static String getStringRepresentation(final int type) {
switch (type) {
case NULL:
return "Null";
@ -149,6 +161,22 @@ abstract public class V8Value implements Releasable {
return v8;
}
/**
* Returns the 'type' of this V8Value. The available types are defined
* as constants in {@link V8Value}. Only types that inherit from
* {@link V8Value} can be returned here.
*
* @return The 'type of this V8Value.
*/
public int getV8Type() {
if (isUndefined()) {
return UNDEFINED;
}
v8.checkThread();
v8.checkReleased();
return v8.getType(v8.getV8RuntimePtr(), objectHandle);
}
/**
* Creates a new Java object pointing at the same V8 Value
* as this. If the value is mutated (by adding new members or
@ -156,7 +184,7 @@ abstract public class V8Value implements Releasable {
* will be updated. Twins are .equal and .strict equals, but
* not == in Java.
*
* Twins must be released separately since they have their own
* Twins must be closed separately since they have their own
* native resources.
*
* @return A new Java object pointing at the same V8 Value
@ -174,10 +202,62 @@ abstract public class V8Value implements Releasable {
}
/**
* Releases the native resources associated with this V8Value.
* Sets the V8Value as weak reference. A weak reference will eventually
* be closed when no more references exist to this object. Once setWeak
* is called, you should check if {@link V8Value#isReleased()} is true
* before invoking any methods on this object.
*
* If any other references exist to this object, the object will not be
* reclaimed. Even if no reference exist, V8 does not give any guarantee
* the object will be closed, so this should only be used if there is no
* other way to track object usage.
*
* @return The receiver.
*/
public V8Value setWeak() {
v8.checkThread();
v8.checkReleased();
v8.v8WeakReferences.put(getHandle(), this);
v8.setWeak(v8.getV8RuntimePtr(), getHandle());
return this;
}
/**
* Clears any weak reference set on this V8Value and makes this a strong
* reference. Strong references will not be garbage collected and this
* Object must be explicitly released.
*
* Calling clearWeak does nothing if the object is not currently set
* to weak.
*
* @return The receiver.
*/
public V8Value clearWeak() {
v8.checkThread();
v8.checkReleased();
v8.v8WeakReferences.remove(getHandle());
v8.clearWeak(v8.getV8RuntimePtr(), getHandle());
return this;
}
/**
* If {@link V8Value#setWeak()} has been called on this Object, this method
* will return true. Otherwise it will return false.
*
* @return Returns true if this object has been set 'Weak', return false otherwise.
*/
public boolean isWeak() {
v8.checkThread();
v8.checkReleased();
return v8.isWeak(v8.getV8RuntimePtr(), getHandle());
}
/*
* (non-Javadoc)
* @see java.io.Closeable#close()
*/
@Override
public void release() {
public void close() {
v8.checkThread();
if (!released) {
try {
@ -189,6 +269,17 @@ abstract public class V8Value implements Releasable {
}
}
/**
* Releases the native resources associated with this V8Value.
*
* @deprecated use close() instead.
*/
@Override
@Deprecated
public void release() {
close();
}
/**
* Determine if the native resources have been released. Once released
* a V8 Value can no longer be used.

43
fine-j2v8/src/com/eclipsesource/v8/debug/DebugHandler.java

@ -105,7 +105,7 @@ public class DebugHandler implements Releasable {
try {
return debugObject.executeIntegerFunction(SET_BREAK_POINT, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -124,7 +124,7 @@ public class DebugHandler implements Releasable {
try {
return debugObject.executeIntegerFunction(SET_SCRIPT_BREAK_POINT_BY_NAME, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -139,7 +139,7 @@ public class DebugHandler implements Releasable {
try {
debugObject.executeVoidFunction(ENABLE_SCRIPT_BREAK_POINT, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -154,7 +154,7 @@ public class DebugHandler implements Releasable {
try {
debugObject.executeVoidFunction(DISABLE_SCRIPT_BREAK_POINT, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -169,7 +169,7 @@ public class DebugHandler implements Releasable {
try {
debugObject.executeVoidFunction(CLEAR_BREAK_POINT, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -190,7 +190,7 @@ public class DebugHandler implements Releasable {
try {
return breakPoints.length();
} finally {
breakPoints.release();
breakPoints.close();
}
}
@ -208,12 +208,12 @@ public class DebugHandler implements Releasable {
try {
result[i] = breakPoint.executeIntegerFunction(NUMBER, null);
} finally {
breakPoint.release();
breakPoint.close();
}
}
return result;
} finally {
breakPoints.release();
breakPoints.close();
}
}
@ -232,9 +232,9 @@ public class DebugHandler implements Releasable {
scriptBreakPoint = debugObject.executeObjectFunction(FIND_SCRIPT_BREAK_POINT, parameters);
return new ScriptBreakPoint(scriptBreakPoint);
} finally {
parameters.release();
parameters.close();
if (scriptBreakPoint != null) {
scriptBreakPoint.release();
scriptBreakPoint.close();
}
}
}
@ -252,13 +252,23 @@ public class DebugHandler implements Releasable {
try {
debugObject.executeVoidFunction(CHANGE_BREAK_POINT_CONDITION, parameters);
} finally {
parameters.release();
parameters.close();
}
}
/*
* (non-Javadoc)
* @see java.io.Closeable#close()
*/
@Override
public void close() {
debugObject.close();
}
@Override
@Deprecated
public void release() {
debugObject.release();
close();
}
private void setupDebugObject(final V8 runtime) {
@ -266,7 +276,7 @@ public class DebugHandler implements Releasable {
try {
debugObject = outerDebug.getObject(V8_DEBUG_OBJECT);
} finally {
outerDebug.release();
outerDebug.close();
}
}
@ -277,14 +287,15 @@ public class DebugHandler implements Releasable {
V8Array parameters = null;
try {
debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER);
parameters = new V8Array(runtime).push(debugHandler);
parameters = new V8Array(runtime);
parameters.push(debugHandler);
debugObject.executeFunction(SET_LISTENER, parameters);
} finally {
if ((debugHandler != null) && !debugHandler.isReleased()) {
debugHandler.release();
debugHandler.close();
}
if ((parameters != null) && !parameters.isReleased()) {
parameters.release();
parameters.close();
}
}
}

10
fine-j2v8/src/com/eclipsesource/v8/debug/EventData.java

@ -25,10 +25,16 @@ public class EventData implements Releasable {
}
@Override
public void release() {
public void close() {
if (!v8Object.isReleased()) {
v8Object.release();
v8Object.close();
}
}
@Override
@Deprecated
public void release() {
close();
}
}

16
fine-j2v8/src/com/eclipsesource/v8/debug/ExecutionState.java

@ -58,7 +58,7 @@ public class ExecutionState implements Releasable {
try {
v8Object.executeVoidFunction(PREPARE_STEP, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -76,19 +76,25 @@ public class ExecutionState implements Releasable {
frame = v8Object.executeObjectFunction(FRAME, parameters);
return new Frame(frame);
} finally {
parameters.release();
parameters.close();
if (frame != null) {
frame.release();
frame.close();
}
}
}
@Override
public void release() {
public void close() {
if ((v8Object != null) && !v8Object.isReleased()) {
v8Object.release();
v8Object.close();
v8Object = null;
}
}
@Override
@Deprecated
public void release() {
close();
}
}

11
fine-j2v8/src/com/eclipsesource/v8/debug/ScriptBreakPoint.java

@ -61,7 +61,7 @@ public class ScriptBreakPoint implements Releasable {
try {
v8Object.executeVoidFunction(SET_CONDITION, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -80,10 +80,15 @@ public class ScriptBreakPoint implements Releasable {
}
@Override
public void release() {
public void close() {
if ((v8Object != null) && !v8Object.isReleased()) {
v8Object.release();
v8Object.close();
v8Object = null;
}
}
@Override
public void release() {
close();
}
}

693
fine-j2v8/src/com/eclipsesource/v8/debug/V8DebugServer.java

@ -0,0 +1,693 @@
/**
* Copyright 2016, Genuitec, LLC
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Genuitec LLC - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.debug;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;
import com.eclipsesource.v8.JavaVoidCallback;
import com.eclipsesource.v8.Releasable;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Function;
import com.eclipsesource.v8.V8Object;
/**
* <p>V8DebugServer enables debuggers to connect to J2V8 via V8 server sockets debug protocol.
* Server has to be created in the same thread as the provided V8 runtime has been created (the V8 thread).
* You can specify port and whether the {@link #start()} method should
* block until a client connects. {@link #setTraceCommunication(boolean)} allows to output
* communication details for debugging purposes. Before creating V8 runtime you need to set V8 flag to expose
* debug object. If you do not intend to set other flags, than you can use {@link #configureV8ForDebugging()}
* method, otherwise set {@code -expose-debug-as=__j2v8_Debug} flag through {@link V8#setFlags(String)}.
*
* <p>Client connection is handled in a separate thread, however, commands are processed in the V8 thread.
* Therefore it is vital to provide an opportunity to process requests by calling
* {@link #processRequests(long)} method from the V8 thread. This will for instance
* allow to install breakpoints before the JavaScript code starts to execute. It is also good to call that
* method when V8 thread is idle to promptly provide responses to the debugger to avoid timeouts.
*
* <p>Example code:
*
* <code><br>
* &nbsp;&nbsp;//configure for debugging before creating runtime<br>
* &nbsp;&nbsp;V8DebugServer.configureV8ForDebugging();<br>
* <br>
* &nbsp;&nbsp;//create V8 runtime<br>
* &nbsp;&nbsp;V8 runtime = V8.createV8Runtime();<br>
* <br>
* &nbsp;&nbsp;//create and start debug server<br>
* &nbsp;&nbsp;int port = 0;<br>
* &nbsp;&nbsp;boolean waitForConnection = true;<br>
* &nbsp;&nbsp;server = new V8DebugServer(runtime, port, waitForConnection);<br>
* &nbsp;&nbsp;System.out.println("V8 Debug Server listening on port "<br>
* &nbsp;&nbsp;&nbsp;&nbsp;+ server.getPort());<br>
* &nbsp;&nbsp;server.start();<br>
* <br>
* &nbsp;&nbsp;//execute script and provide name for it<br>
* &nbsp;&nbsp;runtime.executeVoidScript("var i = 15", "myscript.js", 0);<br>
*
* </code>
*
* @author piotr@genuitec.com
*/
@SuppressWarnings("nls")
public class V8DebugServer {
/**
* Name under which internal V8 debug object is going to be exposed in the runtime.
* You can change the name if you are passing a different one through {@code -expose-debug-as}
* flag.
*/
public static String DEBUG_OBJECT_NAME = "__j2v8_Debug";
private static final String DEBUG_BREAK_HANDLER = "__j2v8_debug_handler";
private static final String MAKE_BREAK_EVENT = "__j2v8_MakeBreakEvent";
private static final String MAKE_COMPILE_EVENT = "__j2v8_MakeCompileEvent";
private static final String SET_LISTENER = "setListener";
private static final String V8_DEBUG_OBJECT = "Debug";
//Headers
private static final String HEADER_TYPE = "Type: ";
private static final String HEADER_V8_VERSION = "V8-Version: ";
private static final String HEADER_PROTOCOL_VERSION = "Protocol-Version: ";
private static final String HEADER_EMBEDDING_HOST = "Embedding-Host: ";
private static final String V8_VERSION = "4.10.253";
private static final String J2V8_VERSION = "4.0.0";
private static final String PROTOCOL_VERSION = "1";
//Protocol consts
private static final Charset PROTOCOL_CHARSET = Charset.forName("UTF-8");
private static final String PROTOCOL_EOL = "\r\n";
private static final byte[] PROTOCOL_EOL_BYTES = PROTOCOL_EOL.getBytes(PROTOCOL_CHARSET);
private static final String PROTOCOL_CONTENT_LENGTH_HEADER = "Content-Length:";
private static final byte[] PROTOCOL_CONTENT_LENGTH_BYTES = PROTOCOL_CONTENT_LENGTH_HEADER.getBytes(PROTOCOL_CHARSET);
private static final int PROTOCOL_BUFFER_SIZE = 4096;
/**
* Utility method for simplification of configuring V8 for debugging support.
*/
public static void configureV8ForDebugging() {
try {
V8.setFlags("-expose-debug-as=" + DEBUG_OBJECT_NAME);
} catch (Throwable t) {
t.printStackTrace();
}
}
private ServerSocket server;
private Socket client;
private Object clientLock = new Object();
private V8 runtime;
private V8Object debugObject;
private V8Object runningStateDcp;
private V8Object stoppedStateDcp;
private boolean waitForConnection;
private boolean traceCommunication = false;
private List<String> requests = new LinkedList<String>();
/**
* Creates V8DebugServer.
*
* @param runtime
* @param port
* @param waitForConnection
*/
public V8DebugServer(final V8 runtime, final int port, final boolean waitForConnection) {
this.runtime = runtime;
this.waitForConnection = waitForConnection;
V8Object debugScope = runtime.getObject(DEBUG_OBJECT_NAME);
if (debugScope == null) {
System.err.println("Cannot initialize debugger server - global debug object not found.");
return;
}
try {
debugObject = debugScope.getObject(V8_DEBUG_OBJECT);
} finally {
debugScope.close();
}
runtime.executeVoidScript("(function() {\n"
+ " " + DEBUG_OBJECT_NAME + ".Debug. " + MAKE_BREAK_EVENT + " = function (break_id,breakpoints_hit) {\n"
+ " return new " + DEBUG_OBJECT_NAME + ".BreakEvent(break_id,breakpoints_hit);\n"
+ " }\n"
+ " " + DEBUG_OBJECT_NAME + ".Debug. " + MAKE_COMPILE_EVENT + " = function(script,type) {\n"
+ " var scripts = " + DEBUG_OBJECT_NAME + ".Debug.scripts()\n"
+ " for (var i in scripts) {\n"
+ " if (scripts[i].id == script.id()) {\n"
+ " return new " + DEBUG_OBJECT_NAME + ".CompileEvent(scripts[i], type);\n"
+ " }\n"
+ " }\n"
+ " return {toJSONProtocol: function() {return ''}}\n"
+ " }\n"
+ "})()");
try {
server = new ServerSocket(port);
} catch (Exception e) {
logError(e);
}
}
/**
* Returns port on which server is listening or -1 if server failed to bound to a port.
* @return port or -1 if server failed to bound to a port
*/
public int getPort() {
return (server != null) && server.isBound() ? server.getLocalPort() : -1;
}
/**
* Output all communication to the console. For purpose of debugging V8DebugServer itself.
* @param value
*/
public void setTraceCommunication(final boolean value) {
traceCommunication = value;
}
/**
* Starts accepting client connections and blocks until a client connects
* if {@code waitForConnection} has been passed to V8DebugServer constructor.
*/
public void start() {
if (server == null) {
return;
}
boolean waitForConnection = this.waitForConnection;
Thread clientThread = new Thread(new ClientLoop(), "J2V8 Debugger Server");
clientThread.setDaemon(true);
clientThread.start();
setupEventHandler();
runningStateDcp = runtime.executeObjectScript("(function() {return new " + DEBUG_OBJECT_NAME + ".DebugCommandProcessor(null, true)})()");
if (waitForConnection) {
synchronized (clientLock) {
while (this.waitForConnection) {
try {
clientLock.wait();
} catch (InterruptedException e) {
//ignore
}
}
}
//Process initial requests
//Give 100ms for initial debugger connection setup
try {
processRequests(100);
} catch (InterruptedException e) {
//ignore
}
}
}
public void stop() {
try {
server.close();
synchronized (clientLock) {
if (client != null) {
client.close();
client = null;
}
}
} catch (IOException e) {
logError(e);
}
//release resources
if (runningStateDcp != null) {
runningStateDcp.close();
runningStateDcp = null;
}
if (debugObject != null) {
debugObject.close();
debugObject = null;
}
if (stoppedStateDcp != null) {
stoppedStateDcp.close();
stoppedStateDcp = null;
}
};
private void sendJson(String json) throws IOException {
json = json.replace("\\/", "/"); // Unescape slashes.
sendMessage("", json);
}
protected void logError(final Throwable t) {
t.printStackTrace();
}
private void sendMessage(final String header, final String contents) throws IOException {
synchronized (clientLock) {
if (!isConnected()) {
throw new IOException("There is no connected client.");
}
byte[] contentBytes = contents.getBytes(PROTOCOL_CHARSET);
StringBuilder sb = new StringBuilder();
//append custom headers
sb.append(header);
//append content length header
sb.append(PROTOCOL_CONTENT_LENGTH_HEADER);
sb.append(Integer.toString(contentBytes.length));
sb.append(PROTOCOL_EOL);
//skip tools info
sb.append(PROTOCOL_EOL);
//send headers to the client
client.getOutputStream().write(sb.toString().getBytes(
PROTOCOL_CHARSET));
//send contents to the client
if (contentBytes.length > 0) {
client.getOutputStream().write(contentBytes);
}
}
}
private boolean isConnected() {
synchronized (clientLock) {
return (server != null) && (client != null) && client.isConnected();
}
}
public void processRequests(final long timeout) throws InterruptedException {
if (server == null) {
return;
}
long start = System.currentTimeMillis();
do {
String[] reqs;
do {
synchronized (requests) {
reqs = requests.toArray(new String[requests.size()]);
requests.clear();
}
for (String req : reqs) {
try {
processRequest(req);
} catch (Exception e) {
logError(e);
}
}
} while (reqs.length > 0);
if (timeout > 0) {
Thread.sleep(10);
}
} while ((timeout > 0) && ((start + timeout) > System.currentTimeMillis()));
}
private void processRequest(final String message) throws IOException {
if (traceCommunication) {
System.out.println("Got message: \n" + message.substring(0, Math.min(message.length(), 1000)));
}
V8Array params = new V8Array(runtime);
params.push(message);
@SuppressWarnings("resource")
V8Object dcp = stoppedStateDcp != null ? stoppedStateDcp : runningStateDcp;
Object result = dcp.executeFunction("processDebugJSONRequest", params);
String json = result.toString();
if ((stoppedStateDcp == null) && json.contains("\"running\":false")) {
//XXX Need to implement functionality by adding to V8 class
// breakpoints before initial script or function execution
json = json.replace("\"running\":false", "\"running\":true")
.replace("\"success\":true", "\"success\":false")
.replace("{\"", "{\"message\":\"Client requested suspension is not supported on J2V8.\",\"");
dcp.add("running_", true);
}
if (traceCommunication) {
System.out.println("Returning response: \n" + json.substring(0, Math.min(json.length(), 1000)));
}
sendJson(json);
}
private void setupEventHandler() {
EventHandler handler = new EventHandler();
debugObject.registerJavaMethod(handler, DEBUG_BREAK_HANDLER);
V8Function debugHandler = null;
V8Array parameters = null;
try {
debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER);
parameters = new V8Array(runtime);
parameters.push(debugHandler);
debugObject.executeFunction(SET_LISTENER, parameters);
} finally {
if ((debugHandler != null) && !debugHandler.isReleased()) {
debugHandler.close();
}
if ((parameters != null) && !parameters.isReleased()) {
parameters.close();
}
}
}
private void enterBreakLoop(final V8Object execState, final V8Object eventData) throws IOException {
try {
V8Array params = new V8Array(runtime);
try {
params.push(false);
stoppedStateDcp = execState.executeObjectFunction("debugCommandProcessor", params);
} finally {
params.close();
}
//send event to debugger
int breakId = execState.getInteger("break_id");
V8Array breakpointsHit = eventData.getArray("break_points_hit_");
V8Object event = null;
params = new V8Array(runtime);
try {
params.push(breakId);
params.push(breakpointsHit);
event = debugObject.executeObjectFunction(MAKE_BREAK_EVENT, params);
String json = event.executeStringFunction("toJSONProtocol", null);
if (traceCommunication) {
System.out.println("Sending event (Break):\n" + json);
}
sendJson(json);
} finally {
params.close();
breakpointsHit.close();
if (event != null) {
event.close();
}
}
//process requests until one of the resumes execution
while (isConnected() && !stoppedStateDcp.executeBooleanFunction("isRunning", null)) {
try {
processRequests(10);
} catch (InterruptedException e) {
//ignore
}
}
} finally {
stoppedStateDcp.close();
stoppedStateDcp = null;
}
}
private void sendCompileEvent(final V8Object eventData) throws IOException {
if (!isConnected()) {
return;
}
//send event to debugger
int type = eventData.getInteger("type_");
V8Object script = eventData.getObject("script_");
V8Object event = null;
V8Array params = new V8Array(runtime);
try {
params.push(script);
params.push(type);
event = debugObject.executeObjectFunction(MAKE_COMPILE_EVENT, params);
String json = event.executeStringFunction("toJSONProtocol", null);
if (traceCommunication) {
System.out.println("Sending event (CompileEvent):\n" + json.substring(0, Math.min(json.length(), 1000)));
}
if (json.length() > 0) {
sendJson(json);
}
} finally {
params.close();
script.close();
if (event != null) {
event.close();
}
}
}
private class EventHandler implements JavaVoidCallback {
@Override
public void invoke(final V8Object receiver, final V8Array parameters) {
if ((parameters == null) || parameters.isUndefined()) {
return;
}
V8Object execState = null;
V8Object eventData = null;
try {
int event = parameters.getInteger(0);
execState = parameters.getObject(1);
eventData = parameters.getObject(2);
if (traceCommunication) {
String type = "unknown";
switch (event) {
case 1:
type = "Break";
break;
case 2:
type = "Exception";
break;
case 3:
type = "NewFunction";
break;
case 4:
type = "BeforeCompile";
break;
case 5:
type = "AfterCompile";
break;
case 6:
type = "CompileError";
break;
case 7:
type = "PromiseEvent";
break;
case 8:
type = "AsyncTaskEvent";
break;
}
System.out.println("V8 has emmitted an event of type " + type);
}
if (!isConnected()) {
return;
}
switch (event) {
case 1: //Break
enterBreakLoop(execState, eventData);
break;
case 5: //afterCompile
case 6: //compileError
sendCompileEvent(eventData);
break;
case 2: //exception
default:
}
} catch (Exception e) {
logError(e);
} finally {
safeRelease(execState);
safeRelease(eventData);
}
}
private void safeRelease(final Releasable object) {
if ((object != null)) {
object.release();
}
}
}
private class ClientLoop implements Runnable {
private int from;
@Override
public void run() {
while (true) {
try {
Socket socket = server.accept();
socket.setTcpNoDelay(true);
synchronized (clientLock) {
client = socket;
waitForConnection = false;
clientLock.notifyAll();
}
startHandshake();
processClientRequests();
} catch (Exception e) {
synchronized (clientLock) {
if (client != null) {
try {
client.close();
} catch (IOException ex) {
//ignore
}
client = null;
}
}
logError(e);
}
}
}
private void startHandshake() throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(HEADER_V8_VERSION);
sb.append(V8_VERSION);
sb.append(PROTOCOL_EOL);
sb.append(HEADER_PROTOCOL_VERSION);
sb.append(PROTOCOL_VERSION);
sb.append(PROTOCOL_EOL);
sb.append(HEADER_EMBEDDING_HOST);
sb.append("j2v8 ");
sb.append(J2V8_VERSION);
sb.append(PROTOCOL_EOL);
sb.append(HEADER_TYPE);
sb.append("connect");
sb.append(PROTOCOL_EOL);
sendMessage(sb.toString(), "");
}
private void processClientRequests() throws IOException {
final byte[] EMPTY_ARR = new byte[] {};
byte[] buf = new byte[PROTOCOL_BUFFER_SIZE];
int bytesRead;
int offset = 0;
//Message data
boolean toolInfoSkipped = false;
byte[] messageBytes = EMPTY_ARR;
int contentLength = -1;
InputStream cIn;
synchronized (clientLock) {
cIn = client.getInputStream();
}
while ((bytesRead = cIn.read(buf, offset, PROTOCOL_BUFFER_SIZE - offset)) > 0) {
bytesRead += offset;
from = 0;
do {
if (contentLength < 0) {
contentLength = readContentLength(buf, bytesRead);
if (contentLength < 0) {
break;
}
}
if (!toolInfoSkipped) {
toolInfoSkipped = skipToolInfo(buf, bytesRead);
if (!toolInfoSkipped) {
break;
}
}
int length = Math.min(contentLength - messageBytes.length, bytesRead - from);
messageBytes = join(messageBytes, buf, from, length);
from += length;
if (messageBytes.length == contentLength) {
String message = new String(messageBytes, PROTOCOL_CHARSET);
synchronized (requests) {
requests.add(message);
}
contentLength = -1;
toolInfoSkipped = false;
messageBytes = EMPTY_ARR;
}
} while (from < bytesRead);
if (from < bytesRead) {
System.arraycopy(buf, from, buf, 0, bytesRead - from);
offset = bytesRead - from;
} else {
offset = 0;
}
}
}
private int readContentLength(final byte[] bytes, final int to) throws IOException {
int pos = indexOf(PROTOCOL_CONTENT_LENGTH_BYTES, bytes, from, to);
if (pos < 0) {
return -1;
}
pos += PROTOCOL_CONTENT_LENGTH_BYTES.length;
int end = indexOf(PROTOCOL_EOL_BYTES, bytes, pos, to);
if (end < 0) {
return -1;
}
String str = new String(bytes, pos, end - pos, PROTOCOL_CHARSET);
int contentLength;
try {
contentLength = Integer.parseInt(str.trim());
} catch (Exception ex) {
throw new IOException("Invalid content length header: '" + str + "' in message" +
new String(bytes, PROTOCOL_CHARSET));
}
from = end + PROTOCOL_EOL_BYTES.length;
return contentLength;
}
private boolean skipToolInfo(final byte[] bytes, final int n) {
int end = indexOf(PROTOCOL_EOL_BYTES, bytes, from, n);
if (end < 0) {
return false;
}
from = end + PROTOCOL_EOL_BYTES.length;
return true;
}
private int indexOf(final byte[] pattern, final byte[] array, final int start, final int end) {
int len = pattern.length;
for (int i = start; i < end; i++) {
for (int j = 0; j <= len; j++) {
if (j == len) {
//pattern matches at i
return i;
}
if (((i + j) >= end) || (array[i + j] != pattern[j])) {
//pattern does not match at i
break;
}
}
}
return -1;
}
private byte[] join(final byte[] arr1, final byte[] arr2, final int startPos, final int length) {
byte[] res = new byte[arr1.length + length];
System.arraycopy(arr1, 0, res, 0, arr1.length);
System.arraycopy(arr2, startPos, res, arr1.length, length);
return res;
}
};
}

44
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Frame.java

@ -19,8 +19,8 @@ import com.eclipsesource.v8.V8Object;
*/
public class Frame extends Mirror {
private static final String END = "end";
private static final String START = "start";
private static final String SOURCE_TEXT = "sourceText";
private static final String FUNC = "func";
private static final String COLUMN = "column";
private static final String LINE = "line";
private static final String POSITION = "position";
@ -56,18 +56,28 @@ public class Frame extends Mirror {
*/
public SourceLocation getSourceLocation() {
V8Object sourceLocation = v8Object.executeObjectFunction(SOURCE_LOCATION, null);
FunctionMirror function = getFunction();
String functionScriptName = function.getScriptName();
try {
String scriptName = null;
V8Object scriptObject = (V8Object) sourceLocation.get(SCRIPT);
String scriptName = scriptObject.getString(NAME);
scriptObject.release();
if (scriptObject != null) {
scriptName = scriptObject.getString(NAME);
scriptObject.close();
}
if ((scriptName == null) && (functionScriptName != null)) {
scriptName = functionScriptName;
} else {
scriptName = "undefined";
}
return new SourceLocation(scriptName,
sourceLocation.getInteger(POSITION),
sourceLocation.getInteger(LINE),
sourceLocation.getInteger(COLUMN),
sourceLocation.getInteger(START),
sourceLocation.getInteger(END));
sourceLocation.getString(SOURCE_TEXT));
} finally {
sourceLocation.release();
function.close();
sourceLocation.close();
}
}
@ -92,7 +102,7 @@ public class Frame extends Mirror {
try {
return v8Object.executeStringFunction(ARGUMENT_NAME, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -113,9 +123,9 @@ public class Frame extends Mirror {
}
return new ValueMirror(result);
} finally {
parameters.release();
parameters.close();
if (result != null) {
result.release();
result.close();
}
}
}
@ -137,9 +147,9 @@ public class Frame extends Mirror {
}
return createMirror(result);
} finally {
parameters.release();
parameters.close();
if (result != null) {
result.release();
result.close();
}
}
}
@ -165,7 +175,7 @@ public class Frame extends Mirror {
try {
return v8Object.executeStringFunction(LOCAL_NAME, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -183,9 +193,9 @@ public class Frame extends Mirror {
scope = v8Object.executeObjectFunction(SCOPE, parameters);
return new Scope(scope);
} finally {
parameters.release();
parameters.close();
if (scope != null) {
scope.release();
scope.close();
}
}
}
@ -198,11 +208,11 @@ public class Frame extends Mirror {
public FunctionMirror getFunction() {
V8Object function = null;
try {
function = v8Object.executeObjectFunction("func", null);
function = v8Object.executeObjectFunction(FUNC, null);
return new FunctionMirror(function);
} finally {
if (function != null) {
function.release();
function.close();
}
}
}

20
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/FunctionMirror.java

@ -17,6 +17,9 @@ import com.eclipsesource.v8.V8Object;
*/
public class FunctionMirror extends ObjectMirror {
private static final String NAME = "name";
private static final String SCRIPT = "script";
FunctionMirror(final V8Object v8Object) {
super(v8Object);
}
@ -27,7 +30,22 @@ public class FunctionMirror extends ObjectMirror {
* @return The name of this function
*/
public String getName() {
return v8Object.executeStringFunction("name", null);
return v8Object.executeStringFunction(NAME, null);
}
/**
* Returns the name of the Script associated with
* this FunctionMirror.
*
* @return The name of the script.
*/
public String getScriptName() {
V8Object script = v8Object.executeObjectFunction(SCRIPT, null);
try {
return script.executeStringFunction(NAME, null);
} finally {
script.close();
}
}
@Override

18
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Mirror.java

@ -156,14 +156,28 @@ public class Mirror implements Releasable {
return false;
}
/*
* (non-Javadoc)
* @see java.io.Closeable#close()
*/
@Override
public void release() {
public void close() {
if ((v8Object != null) && !v8Object.isReleased()) {
v8Object.release();
v8Object.close();
v8Object = null;
}
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.Releasable#release()
*/
@Override
@Deprecated
public void release() {
close();
}
protected static boolean isValue(final V8Object mirror) {
try {
return mirror.executeBooleanFunction(IS_VALUE, null);

8
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/ObjectMirror.java

@ -64,9 +64,9 @@ public class ObjectMirror extends ValueMirror {
}
return result;
} finally {
parameters.release();
parameters.close();
if (propertyNames != null) {
propertyNames.release();
propertyNames.close();
}
}
}
@ -87,9 +87,9 @@ public class ObjectMirror extends ValueMirror {
result = v8Object.executeArrayFunction(PROPERTIES, parameters);
return new PropertiesArray(result);
} finally {
parameters.release();
parameters.close();
if ((result != null) && !result.isReleased()) {
result.release();
result.close();
result = null;
}
}

20
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/PropertiesArray.java

@ -36,17 +36,31 @@ public class PropertiesArray implements Releasable {
try {
return new PropertyMirror(result);
} finally {
result.release();
result.close();
}
}
/*
* (non-Javadoc)
* @see java.io.Closeable#close()
*/
@Override
public void release() {
public void close() {
if (!v8Array.isReleased()) {
v8Array.release();
v8Array.close();
}
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.Releasable#release()
*/
@Override
@Deprecated
public void release() {
close();
}
/**
* Returns the number of properties contained in this array.
*

2
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/PropertyMirror.java

@ -40,7 +40,7 @@ public class PropertyMirror extends Mirror {
try {
return createMirror(mirror);
} finally {
mirror.release();
mirror.close();
}
}

12
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/Scope.java

@ -63,7 +63,7 @@ public class Scope extends Mirror {
try {
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -80,7 +80,7 @@ public class Scope extends Mirror {
try {
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -97,7 +97,7 @@ public class Scope extends Mirror {
try {
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -114,7 +114,7 @@ public class Scope extends Mirror {
try {
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -131,7 +131,7 @@ public class Scope extends Mirror {
try {
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters);
} finally {
parameters.release();
parameters.close();
}
}
@ -147,7 +147,7 @@ public class Scope extends Mirror {
return (ObjectMirror) createMirror(mirror);
} finally {
if ( mirror != null ) {
mirror.release();
mirror.close();
}
}

30
fine-j2v8/src/com/eclipsesource/v8/debug/mirror/SourceLocation.java

@ -19,8 +19,7 @@ public class SourceLocation {
private final int position;
private final int line;
private final int column;
private final int start;
private final int end;
private String sourceText;
/**
* Represents a JS Script Source Location
@ -28,21 +27,19 @@ public class SourceLocation {
* @param position The position in the script
* @param line The line number
* @param column The column number
* @param start The start of this location
* @param end The end of this location
* @param sourceText The sourceCode at this location
*/
public SourceLocation(final String scriptName, final int position, final int line, final int column, final int start, final int end) {
public SourceLocation(final String scriptName, final int position, final int line, final int column, final String sourceText) {
this.scriptName = scriptName;
this.position = position;
this.line = line;
this.column = column;
this.start = start;
this.end = end;
this.sourceText = sourceText;
}
@Override
public String toString() {
return scriptName + " : " + position + " : " + line + " : " + column + " : " + start + " : " + end;
return scriptName + " : " + position + " : " + line + " : " + column + " : " + sourceText;
}
/**
@ -78,19 +75,10 @@ public class SourceLocation {
}
/**
* Returns the start of this SourceLocation.
* @return The start of this SourceLocation.
* Returns the source text for this SourceLocation.
* @return The source text for this SourceLocation.
*/
public int getStart() {
return start;
public String getSourceText() {
return sourceText;
}
/**
* Returns the end of this SourceLocation.
* @return The end of this SourceLocation.
*/
public int getEnd() {
return end;
}
}

69
fine-j2v8/src/com/eclipsesource/v8/utils/ArrayBuffer.java

@ -0,0 +1,69 @@
package com.eclipsesource.v8.utils;
/*******************************************************************************
* Copyright (c) 2019 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8ArrayBuffer;
/**
* A lightweight handle to a V8TypedArray. This handle provides
* access to a V8TypedArray. This handle does not need to be
* closed, but if the type array is accessed using getV8TypedArray
* then the result must be closed.
*
* The underlying V8TypedArray may be reclaimed by the JavaScript
* garbage collector. To check if it's still available, use
* isAvailable.
*/
public class ArrayBuffer {
private V8ArrayBuffer arrayBuffer;
ArrayBuffer(final V8ArrayBuffer arrayBuffer) {
this.arrayBuffer = (V8ArrayBuffer) arrayBuffer.twin().setWeak();
}
/**
* Create a new ArrayBuffer from a java.nio.ByteBuffer
*
* @param v8 the Runtime on which to create the ArrayBuffer
* @param byteBuffer the ByteBuffer to use to back the ArrayBuffer
*/
public ArrayBuffer(final V8 v8, final ByteBuffer byteBuffer) {
V8ArrayBuffer v8ArrayBuffer = new V8ArrayBuffer(v8, byteBuffer);
try {
arrayBuffer = (V8ArrayBuffer) v8ArrayBuffer.twin().setWeak();
} finally {
v8ArrayBuffer.close();
}
}
/**
* Determine if the underlying V8ArrayBuffer is still available, or if it's been cleaned up by the JavaScript
* garbage collector.
*
* @return true if the underlying V8ArrayBuffer is still available, false otherwise.
*/
public boolean isAvailable() {
return !arrayBuffer.isReleased();
}
/**
* Returns the underlying V8ArrayBuffer.
* @return the underlying V8ArrayBuffer.
*/
public V8ArrayBuffer getV8ArrayBuffer() {
return arrayBuffer.twin();
}
}

94
fine-j2v8/src/com/eclipsesource/v8/utils/ConcurrentV8.java

@ -0,0 +1,94 @@
/*******************************************************************************
* Copyright (c) 2016 Brandon Sanders
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Brandon Sanders - initial API and implementation and/or initial documentation
******************************************************************************/
package com.eclipsesource.v8.utils;
import com.eclipsesource.v8.V8;
/**
* Wrapper class for an {@link com.eclipsesource.v8.V8} instance that allows
* a V8 instance to be invoked from across threads without explicitly acquiring
* or releasing locks.
*
* This class does not guarantee the safety of any objects stored in or accessed
* from the wrapped V8 instance; it only enables callers to interact with a V8
* instance from any thread. The V8 instance represented by this class should
* still be treated with thread safety in mind
*
* @author Brandon Sanders [brandon@alicorn.io]
* @author R. Ian Bull - Additional API
*/
public final class ConcurrentV8 {
private V8 v8 = null;
/**
* Create a new ConcurrentV8. A ConcurrentV8 allows multiple
* threads to work with the same V8 engine by releasing
* the locks between calls.
*/
public ConcurrentV8() {
v8 = V8.createV8Runtime();
v8.getLocker().release();
}
/**
* Returns the V8 runtime backing by this ConcurrentV8
*
* @return The V8 runtime backing this ConcurrentV8
*/
public V8 getV8() {
return v8;
}
/**
* Runs an {@link V8Runnable} on the V8 thread.
*
* <b>Note: </b> This method executes synchronously, not asynchronously;
* it will not return until the passed {@link V8Runnable} is done
* executing. The method is also synchronized, so it will block until it
* gets a chance to run.
*
* @param runnable {@link V8Runnable} to run.
*/
public synchronized void run(final V8Runnable runnable) {
try {
v8.getLocker().acquire();
runnable.run(v8);
} finally {
if ((v8 != null) && (v8.getLocker() != null) && v8.getLocker().hasLock()) {
v8.getLocker().release();
}
}
}
/**
* Releases the underlying {@link V8} instance.
*
* This method should be invoked once you're done using this object,
* otherwise a large amount of garbage could be left on the JVM due to
* native resources.
*
* <b>Note:</b> If this method has already been called once, it
* will do nothing.
*/
public void release() {
if ((v8 != null) && !v8.isReleased()) {
// Release the V8 instance from the V8 thread context.
run(new V8Runnable() {
@Override
public void run(final V8 v8) {
if ((v8 != null) && !v8.isReleased()) {
v8.close();
}
}
});
}
}
}

2
fine-j2v8/src/com/eclipsesource/v8/utils/MemoryManager.java

@ -98,7 +98,7 @@ public class MemoryManager {
releasing = true;
try {
for (V8Value reference : references) {
reference.release();
reference.close();
}
v8.removeReferenceHandler(memoryManagerReferenceHandler);
references.clear();

55
fine-j2v8/src/com/eclipsesource/v8/utils/SingleTypeAdapter.java

@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2017 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils;
/**
* Adapt all instances of a single type from JavaScript to Java.
* The TypeAdapter can be used with the V8ObjectUtils to allow users to customize
* the conversion.
*/
public abstract class SingleTypeAdapter implements TypeAdapter {
private int typeToAdapt;
/**
* Create a SingleTypeAdapter
*
* @param typeToAdapt The V8 Type this TypeAdapter should be applied to.
*/
public SingleTypeAdapter(final int typeToAdapt) {
this.typeToAdapt = typeToAdapt;
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.TypeAdapter#adapt(int, java.lang.Object)
*/
@Override
public Object adapt(final int type, final Object value) {
if (type == typeToAdapt) {
return adapt(value);
}
return TypeAdapter.DEFAULT;
}
/**
* Adapt an object from V8 to Java.
*
* If the value is a V8Value (V8Object) then it will be released after
* this method is called. If you wish to retain the object, call
* ((V8Value)value).twin();
*
* @param value The V8 Object to be converted.
* @return The adapted Java Object or {@link TypeAdapter#DEFAULT} for the default conversion.
*/
public abstract Object adapt(final Object value);
}

39
fine-j2v8/src/com/eclipsesource/v8/utils/TypeAdapter.java

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2017 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils;
/**
* An interface which allows a plug-able conversion from V8Value types to Java objects.
* The TypeAdapter can be used with the V8ObjectUtils to allow users to customize
* the conversion.
*/
public interface TypeAdapter {
/**
* A default adapter that if returned in {@link TypeAdapter#adapt(int, Object)}, will result
* in the default type adaption.
*/
public static final Object DEFAULT = new Object();
/**
* Adapt an object from V8 to Java.
*
* If the value is a V8Value (V8Object) then it will be released after
* this method is called. If you wish to retain the object, call
* ((V8Value)value).twin();
*
* @param type The Type of the object to be adapted.
* @param value The V8 Object to be converted.
* @return The adapted Java Object or {@link TypeAdapter#DEFAULT} for the default conversion.
*/
public Object adapt(int type, Object value);
}

73
fine-j2v8/src/com/eclipsesource/v8/utils/TypedArray.java

@ -0,0 +1,73 @@
package com.eclipsesource.v8.utils;
/*******************************************************************************
* Copyright (c) 2019 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8ArrayBuffer;
import com.eclipsesource.v8.V8TypedArray;
/**
* A lightweight handle to a V8TypedArray. This handle provides
* access to a V8TypedArray. This handle does not need to be
* closed, but if the type array is accessed using getV8TypedArray
* then the result must be closed.
*
* The underlying V8TypedArray may be reclaimed by the JavaScript
* garbage collector. To check if it's still available, use
* isAvailable.
*/
public class TypedArray {
private V8TypedArray typedArray;
TypedArray(final V8TypedArray typedArray) {
this.typedArray = (V8TypedArray) typedArray.twin().setWeak();
}
/**
* Create a new TypedArray from an ArrayBuffer.
*
* @param v8 the V8Runtime on which to create the TypedArray
* @param buffer the ArrayBuffer to use to back the TypedArray
* @param type the Type of Array to create
* @param offset the Offset into the ArrayBuffer in which to map the TyepdArray
* @param size the Size of the TypedArray
*/
public TypedArray(final V8 v8, final ArrayBuffer buffer, final int type, final int offset, final int size) {
V8ArrayBuffer v8ArrayBuffer = buffer.getV8ArrayBuffer();
V8TypedArray v8typedArray = new V8TypedArray(v8, v8ArrayBuffer, type, offset, size);
try {
typedArray = (V8TypedArray) v8typedArray.twin().setWeak();
} finally {
v8ArrayBuffer.close();
v8typedArray.close();
}
}
/**
* Determine if the underlying V8TypedArray is still available, or if it's been cleaned up by the JavaScript
* garbage collector.
*
* @return true if the underlying V8TypedArray is still available, false otherwise.
*/
public boolean isAvailable() {
return !typedArray.isReleased();
}
/**
* Returns the underlying V8TypedArray.
* @return the underlying V8TypedArray.
*/
public V8TypedArray getV8TypedArray() {
return (V8TypedArray) typedArray.twin();
}
}

6
fine-j2v8/src/com/eclipsesource/v8/utils/V8Executor.java

@ -149,8 +149,8 @@ public class V8Executor extends Thread {
parameters.push(strings);
runtime.executeVoidFunction(messageHandler, parameters);
} finally {
strings.release();
parameters.release();
strings.close();
parameters.close();
}
}
}
@ -159,7 +159,7 @@ public class V8Executor extends Thread {
} finally {
synchronized (this) {
if (runtime.getLocker().hasLock()) {
runtime.release();
runtime.close();
runtime = null;
}
terminated = true;

20
fine-j2v8/src/com/eclipsesource/v8/utils/V8Map.java

@ -40,14 +40,24 @@ public class V8Map<V> implements Map<V8Value, V>, Releasable {
twinMap = new HashMap<V8Value, V8Value>();
}
/*
* (non-Javadoc)
* @see java.io.Closeable#close()
*/
@Override
public void close() {
this.clear();
}
/**
* Releases all the resources associated with this map. A
* map can be used again once it's released, although
* if it's used again it should be released again.
*/
@Override
@Deprecated
public void release() {
this.clear();
close();
}
/*
@ -116,7 +126,7 @@ public class V8Map<V> implements Map<V8Value, V>, Releasable {
V result = map.remove(key);
V8Value twin = twinMap.remove(key);
if (twin != null) {
twin.release();
twin.close();
}
return result;
}
@ -127,7 +137,7 @@ public class V8Map<V> implements Map<V8Value, V>, Releasable {
*/
@Override
public void putAll(final Map<? extends V8Value, ? extends V> m) {
for (Entry<? extends V8Value, ? extends V> entry : m.entrySet()) {
for (java.util.Map.Entry<? extends V8Value, ? extends V> entry : m.entrySet()) {
this.put(entry.getKey(), entry.getValue());
}
}
@ -140,7 +150,7 @@ public class V8Map<V> implements Map<V8Value, V>, Releasable {
public void clear() {
map.clear();
for (V8Value V8Value : twinMap.keySet()) {
V8Value.release();
V8Value.close();
}
twinMap.clear();
}
@ -168,7 +178,7 @@ public class V8Map<V> implements Map<V8Value, V>, Releasable {
* @see java.util.Map#entrySet()
*/
@Override
public Set<Entry<V8Value, V>> entrySet() {
public Set<java.util.Map.Entry<V8Value, V>> entrySet() {
return map.entrySet();
}

440
fine-j2v8/src/com/eclipsesource/v8/utils/V8ObjectUtils.java

@ -10,7 +10,6 @@
******************************************************************************/
package com.eclipsesource.v8.utils;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
@ -18,23 +17,13 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.eclipsesource.v8.Releasable;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8ArrayBuffer;
import com.eclipsesource.v8.V8Object;
import com.eclipsesource.v8.V8TypedArray;
import com.eclipsesource.v8.V8Value;
import com.eclipsesource.v8.utils.typedarrays.ArrayBuffer;
import com.eclipsesource.v8.utils.typedarrays.Float32Array;
import com.eclipsesource.v8.utils.typedarrays.Float64Array;
import com.eclipsesource.v8.utils.typedarrays.Int16Array;
import com.eclipsesource.v8.utils.typedarrays.Int32Array;
import com.eclipsesource.v8.utils.typedarrays.Int8Array;
import com.eclipsesource.v8.utils.typedarrays.TypedArray;
import com.eclipsesource.v8.utils.typedarrays.UInt16Array;
import com.eclipsesource.v8.utils.typedarrays.UInt32Array;
import com.eclipsesource.v8.utils.typedarrays.UInt8Array;
import com.eclipsesource.v8.utils.typedarrays.UInt8ClampedArray;
/**
* A set of static helper methods to convert V8Objects / V8Arrays to
@ -44,6 +33,56 @@ import com.eclipsesource.v8.utils.typedarrays.UInt8ClampedArray;
public class V8ObjectUtils {
private static final Object IGNORE = new Object();
private static final TypeAdapter DEFAULT_TYPE_ADAPTER = new DefaultTypeAdapter();
/**
* Create a Java Object from a result from V8. V8 can return
* basic Java types, or V8Values (V8Object, V8Array, etc...). This method
* will attempt to convert the result into a pure Java object using a
* deep copy.
*
* If the input is basic Java type (Integer, Double, Boolean, String)
* it will be returned. If the input is a V8Value, it will be converted.
*
* All elements in the V8Object are released after they are accessed.
* However, the root object itself is not released.
*
* @param v8Object The input to convert.
* @return A Java object representing the input.
*/
public static Object getValue(final Object v8Object) {
return getValue(v8Object, DEFAULT_TYPE_ADAPTER);
}
/**
* Create a Java Object from a result from V8 using a {@link TypeAdapter} to convert
* objects. V8 can return basic Java types or V8Values (V8Object, V8Array, etc...). This
* method will attempt to convert the result into a pure Java object using
* a deep copy.
*
* If the input is basic Java type (Integer, Double, Boolean, String)
* it will be returned. If the input is a V8Value, it will be converted.
*
* All elements in the V8Object are released after they are accessed.
* However, the root object itself is not released.
*
* @param v8Object The input to convert.
* @param adapter The {@link TypeAdapter} to use for the object conversions.
* @return A Java object representing the input.
*/
public static Object getValue(final Object v8Object, final TypeAdapter adapter) {
V8Map<Object> cache = new V8Map<Object>();
try {
if (v8Object instanceof V8Value) {
int type = ((V8Value) v8Object).getV8Type();
return getValue(v8Object, type, cache, adapter);
} else {
return v8Object;
}
} finally {
cache.close();
}
}
/**
* Creates a Map from a V8Object using a deep copy. All elements
@ -55,11 +94,25 @@ public class V8ObjectUtils {
* @return A map representing a deep copy of the V8Object rooted at 'object'.
*/
public static Map<String, ? super Object> toMap(final V8Object object) {
return toMap(object, DEFAULT_TYPE_ADAPTER);
}
/**
* Creates a Map from a V8Object using a deep copy and a TypeAdapter to handle
* type conversions. 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.
* @param adapter The {@link TypeAdapter} to use for the object conversions.
*
* @return A map representing a deep copy of the V8Object rooted at 'object'.
*/
public static Map<String, ? super Object> toMap(final V8Object object, final TypeAdapter adapter) {
V8Map<Object> cache = new V8Map<Object>();
try {
return toMap(object, cache);
return toMap(object, cache, adapter);
} finally {
cache.release();
cache.close();
}
}
@ -73,11 +126,25 @@ public class V8ObjectUtils {
* @return A list representing a deep copy of the V8Array rooted at 'array'.
*/
public static List<? super Object> toList(final V8Array array) {
return toList(array, DEFAULT_TYPE_ADAPTER);
}
/**
* 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);
return toList(array, cache, adapter);
} finally {
cache.release();
cache.close();
}
}
@ -179,7 +246,7 @@ public class V8ObjectUtils {
return toV8Object(v8, map, cache).twin();
} finally {
for (V8Value v8Object : cache.values()) {
v8Object.release();
v8Object.close();
}
}
}
@ -199,7 +266,7 @@ public class V8ObjectUtils {
return toV8Array(v8, list, cache).twin();
} finally {
for (V8Value v8Object : cache.values()) {
v8Object.release();
v8Object.close();
}
}
}
@ -225,13 +292,13 @@ public class V8ObjectUtils {
Map<Object, V8Value> cache = new Hashtable<Object, V8Value>();
try {
Object result = getV8Result(v8, value, cache);
if (result instanceof V8Object) {
return ((V8Object) result).twin();
if (result instanceof V8Value) {
return ((V8Value) result).twin();
}
return result;
} finally {
for (V8Value v8Object : cache.values()) {
v8Object.release();
v8Object.close();
}
}
}
@ -252,7 +319,7 @@ public class V8ObjectUtils {
pushValue(v8, array, value, cache);
} finally {
for (V8Value v8Object : cache.values()) {
v8Object.release();
v8Object.close();
}
}
}
@ -271,10 +338,55 @@ public class V8ObjectUtils {
*/
public static Object getValue(final V8Array array, final int index) {
V8Map<Object> cache = new V8Map<Object>();
Object object = null;
int type = V8Value.UNDEFINED;
try {
return getValue(array, index, cache);
object = array.get(index);
type = array.getType(index);
Object result = getValue(object, type, cache, DEFAULT_TYPE_ADAPTER);
if ((result == object) && (result instanceof V8Value)) {
return ((V8Value) result).twin();
}
return result;
} finally {
cache.release();
if (object instanceof Releasable) {
((Releasable) object).release();
}
cache.close();
}
}
/**
* Gets a Java Object representing the value at the given index in the V8Array.
* A TypeAdapter is used to convert values from V8Objects to Java Objects.
* If the value is a primitive (int, boolean or double) then a boxed instance
* is returned. If the value is a String, then a String is returned. If
* the value is a V8Object or V8Array, then a Map or List is returned.
*
* @param array The array on which to lookup the value. The array is not
* released.
* @param index The index whose element to lookup.
* @param adapter The {@link TypeAdapter} to use for the object conversions.
*
* @return A Java Object representing the value at a given index.
*/
public static Object getValue(final V8Array array, final int index, final TypeAdapter adapter) {
V8Map<Object> cache = new V8Map<Object>();
Object object = null;
int type = V8Value.UNDEFINED;
try {
object = array.get(index);
type = array.getType(index);
Object result = getValue(object, type, cache, adapter);
if ((result == object) && (result instanceof V8Value)) {
return ((V8Value) result).twin();
}
return result;
} finally {
if (object instanceof Releasable) {
((Releasable) object).release();
}
cache.close();
}
}
@ -291,36 +403,75 @@ public class V8ObjectUtils {
* @return A Java Object representing the value at a given key.
*/
public static Object getValue(final V8Object object, final String key) {
return getValue(object, key, DEFAULT_TYPE_ADAPTER);
}
/**
* Gets a Java Object representing the value with the given key in the V8Object.
* A TypeAdapter is used to convert values from V8Objects to Java Objects.
* If the value is a primitive (int, boolean or double) then a boxed instance
* is returned. If the value is a String, then a String is returned. If
* the value is a V8Object or V8Array, then a Map or List is returned.
*
* @param v8Object The object on which to lookup the value. The object is not
* released.
* @param key The key to use to lookup the value.
* @param adapter The {@link TypeAdapter} to use for the object conversions.
*
* @return A Java Object representing the value at a given key.
*/
public static Object getValue(final V8Object v8Object, final String key, final TypeAdapter adapter) {
V8Map<Object> cache = new V8Map<Object>();
Object object = null;
int type = V8Value.UNDEFINED;
try {
return getValue(object, key, cache);
object = v8Object.get(key);
type = v8Object.getType(key);
Object result = getValue(object, type, cache, adapter);
if ((result == object) && (result instanceof V8Value)) {
return ((V8Value) result).twin();
}
return result;
} finally {
cache.release();
if (object instanceof Releasable) {
((Releasable) object).release();
}
cache.close();
}
}
@SuppressWarnings("unchecked")
private static Map<String, ? super Object> toMap(final V8Object object, final V8Map<Object> cache) {
if (object == null) {
private static Map<String, ? super Object> toMap(final V8Object v8Object, final V8Map<Object> cache, final TypeAdapter adapter) {
if (v8Object == null) {
return Collections.emptyMap();
}
if (cache.containsKey(object)) {
return (Map<String, ? super Object>) cache.get(object);
if (cache.containsKey(v8Object)) {
return (Map<String, ? super Object>) cache.get(v8Object);
}
Map<String, ? super Object> result = new V8PropertyMap<Object>();
cache.put(object, result);
String[] keys = object.getKeys();
cache.put(v8Object, result);
String[] keys = v8Object.getKeys();
for (String key : keys) {
Object value = getValue(object, key, cache);
Object object = null;
int type = V8Value.UNDEFINED;
try {
object = v8Object.get(key);
type = v8Object.getType(key);
Object value = getValue(object, type, cache, adapter);
if (value != IGNORE) {
result.put(key, value);
}
} finally {
if (object instanceof Releasable) {
((Releasable) object).release();
}
}
}
return result;
}
@SuppressWarnings("unchecked")
private static List<? super Object> toList(final V8Array array, final V8Map<Object> cache) {
private static List<? super Object> toList(final V8Array array, final V8Map<Object> cache, final TypeAdapter adapter) {
if (array == null) {
return Collections.emptyList();
}
@ -330,11 +481,39 @@ public class V8ObjectUtils {
List<? super Object> result = new ArrayList<Object>();
cache.put(array, result);
for (int i = 0; i < array.length(); i++) {
Object value = getValue(array, i, cache);
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(getValue(array, i, cache));
result.add(value);
}
} finally {
if (object instanceof Releasable) {
((Releasable) object).release();
}
}
}
return result;
}
private static V8TypedArray toV8TypedArray(final V8 v8, final TypedArray typeArray, final Map<Object, V8Value> cache) {
if (cache.containsKey(typeArray)) {
return (V8TypedArray) cache.get(typeArray);
}
V8TypedArray result = typeArray.getV8TypedArray();
cache.put(typeArray, result);
return result;
}
private static V8ArrayBuffer toV8ArrayBuffer(final V8 v8, final ArrayBuffer arrayBuffer, final Map<Object, V8Value> cache) {
if (cache.containsKey(arrayBuffer)) {
return (V8ArrayBuffer) cache.get(arrayBuffer);
}
V8ArrayBuffer result = arrayBuffer.getV8ArrayBuffer();
cache.put(arrayBuffer, result);
return result;
}
@ -349,7 +528,7 @@ public class V8ObjectUtils {
setValue(v8, result, entry.getKey(), entry.getValue(), cache);
}
} catch (IllegalStateException e) {
result.release();
result.close();
throw e;
}
return result;
@ -367,35 +546,12 @@ public class V8ObjectUtils {
pushValue(v8, result, value, cache);
}
} catch (IllegalStateException e) {
result.release();
result.close();
throw e;
}
return result;
}
private static V8ArrayBuffer toV8ArrayBuffer(final V8 v8, final ArrayBuffer arrayBuffer, final Map<Object, V8Value> cache) {
if (cache.containsKey(arrayBuffer)) {
return (V8ArrayBuffer) cache.get(arrayBuffer);
}
V8ArrayBuffer result = new V8ArrayBuffer(v8, arrayBuffer.getByteBuffer());
cache.put(arrayBuffer, result);
return result;
}
private static V8TypedArray toV8TypedArray(final V8 v8, final TypedArray typedArray, final Map<Object, V8Value> cache) {
if (cache.containsKey(typedArray)) {
return (V8TypedArray) cache.get(typedArray);
}
V8ArrayBuffer arrayBuffer = new V8ArrayBuffer(v8, typedArray.getByteBuffer());
try {
V8TypedArray result = new V8TypedArray(v8, arrayBuffer, typedArray.getType(), 0, typedArray.length());
cache.put(typedArray, result);
return result;
} finally {
arrayBuffer.release();
}
}
@SuppressWarnings("unchecked")
private static Object getV8Result(final V8 v8, final Object value, final Map<Object, V8Value> cache) {
if (cache.containsKey(value)) {
@ -413,30 +569,30 @@ public class V8ObjectUtils {
return value;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes", "resource" })
private static void pushValue(final V8 v8, final V8Array result, final Object value, final Map<Object, V8Value> cache) {
if (value == null) {
result.pushUndefined();
} else if (value instanceof Integer) {
result.push((Integer) value);
result.push(value);
} else if (value instanceof Long) {
result.push(new Double((Long) value));
} else if (value instanceof Double) {
result.push((Double) value);
result.push(value);
} else if (value instanceof Float) {
result.push((Float) value);
result.push(value);
} else if (value instanceof String) {
result.push((String) value);
} else if (value instanceof Boolean) {
result.push((Boolean) value);
} else if (value instanceof V8Object) {
result.push((V8Object) value);
result.push(value);
} else if (value instanceof TypedArray) {
V8TypedArray v8TypedArray = toV8TypedArray(v8, (TypedArray) value, cache);
result.push(v8TypedArray);
} else if (value instanceof ArrayBuffer) {
V8ArrayBuffer v8ArrayBuffer = toV8ArrayBuffer(v8, (ArrayBuffer) value, cache);
result.push(v8ArrayBuffer);
} else if (value instanceof V8Value) {
result.push((V8Value) value);
} else if (value instanceof Map) {
V8Object object = toV8Object(v8, (Map) value, cache);
result.push(object);
@ -448,14 +604,14 @@ public class V8ObjectUtils {
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked", "rawtypes", "resource" })
private static void setValue(final V8 v8, final V8Object result, final String key, final Object value, final Map<Object, V8Value> cache) {
if (value == null) {
result.addUndefined(key);
} else if (value instanceof Integer) {
result.add(key, (Integer) value);
} else if (value instanceof Long) {
result.add(key, (int) (long) (Long) value);
result.add(key, (Long) value);
} else if (value instanceof Double) {
result.add(key, (Double) value);
} else if (value instanceof Float) {
@ -464,14 +620,14 @@ public class V8ObjectUtils {
result.add(key, (String) value);
} else if (value instanceof Boolean) {
result.add(key, (Boolean) value);
} else if (value instanceof V8Object) {
result.add(key, (V8Object) value);
} else if (value instanceof TypedArray) {
V8TypedArray typedArray = toV8TypedArray(v8, (TypedArray) value, cache);
result.add(key, typedArray);
V8TypedArray v8TypedArray = toV8TypedArray(v8, (TypedArray) value, cache);
result.add(key, v8TypedArray);
} else if (value instanceof ArrayBuffer) {
V8ArrayBuffer v8ArrayBuffer = toV8ArrayBuffer(v8, (ArrayBuffer) value, cache);
result.add(key, v8ArrayBuffer);
} else if (value instanceof V8Value) {
result.add(key, (V8Value) value);
} else if (value instanceof Map) {
V8Object object = toV8Object(v8, (Map) value, cache);
result.add(key, object);
@ -483,142 +639,33 @@ public class V8ObjectUtils {
}
}
private static Object getValue(final V8Array array, final int index, final V8Map<Object> cache) {
int valueType = array.getType(index);
switch (valueType) {
case V8Value.INTEGER:
return array.getInteger(index);
case V8Value.DOUBLE:
return array.getDouble(index);
case V8Value.BOOLEAN:
return array.getBoolean(index);
case V8Value.STRING:
return array.getString(index);
case V8Value.V8_FUNCTION:
return IGNORE;
case V8Value.V8_ARRAY_BUFFER:
V8ArrayBuffer buffer = (V8ArrayBuffer) array.get(index);
try {
return new ArrayBuffer(buffer.getBackingStore());
} finally {
buffer.release();
private static Object getValue(final Object value, final int valueType, final V8Map<Object> cache, final TypeAdapter adapter) {
Object adapterResult = adapter.adapt(valueType, value);
if (TypeAdapter.DEFAULT != adapterResult) {
return adapterResult;
}
case V8Value.V8_TYPED_ARRAY:
V8Array typedArray = array.getArray(index);
try {
return toTypedArray(typedArray);
} finally {
if (typedArray instanceof V8Array) {
typedArray.release();
}
}
case V8Value.V8_ARRAY:
V8Array arrayValue = array.getArray(index);
try {
return toList(arrayValue, cache);
} finally {
if (arrayValue instanceof V8Array) {
arrayValue.release();
}
}
case V8Value.V8_OBJECT:
V8Object objectValue = array.getObject(index);
try {
return toMap(objectValue, cache);
} finally {
if (objectValue instanceof V8Object) {
objectValue.release();
}
}
case V8Value.NULL:
return null;
case V8Value.UNDEFINED:
return V8.getUndefined();
default:
throw new IllegalStateException("Cannot find type for index: " + index);
}
}
private static Object toTypedArray(final V8Array typedArray) {
int arrayType = typedArray.getType();
ByteBuffer buffer = ((V8TypedArray) typedArray).getByteBuffer();
switch (arrayType) {
case V8Value.INT_8_ARRAY:
return new Int8Array(buffer);
case V8Value.UNSIGNED_INT_8_ARRAY:
return new UInt8Array(buffer);
case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY:
return new UInt8ClampedArray(buffer);
case V8Value.INT_16_ARRAY:
return new Int16Array(buffer);
case V8Value.UNSIGNED_INT_16_ARRAY:
return new UInt16Array(buffer);
case V8Value.INT_32_ARRAY:
return new Int32Array(buffer);
case V8Value.UNSIGNED_INT_32_ARRAY:
return new UInt32Array(buffer);
case V8Value.FLOAT_32_ARRAY:
return new Float32Array(buffer);
case V8Value.FLOAT_64_ARRAY:
return new Float64Array(buffer);
default:
throw new IllegalStateException("Known Typed Array type: " + V8Value.getStringRepresentaion(arrayType));
}
}
private static Object getValue(final V8Object object, final String key, final V8Map<Object> cache) {
int valueType = object.getType(key);
switch (valueType) {
case V8Value.INTEGER:
return object.getInteger(key);
case V8Value.DOUBLE:
return object.getDouble(key);
case V8Value.BOOLEAN:
return object.getBoolean(key);
case V8Value.STRING:
return object.getString(key);
return value;
case V8Value.V8_FUNCTION:
return IGNORE;
case V8Value.V8_ARRAY_BUFFER:
V8ArrayBuffer buffer = (V8ArrayBuffer) object.get(key);
try {
return new ArrayBuffer(buffer.getBackingStore());
} finally {
buffer.release();
}
return new ArrayBuffer((V8ArrayBuffer) value);
case V8Value.V8_TYPED_ARRAY:
V8Array typedArray = object.getArray(key);
try {
return toTypedArray(typedArray);
} finally {
if (typedArray instanceof V8Array) {
typedArray.release();
}
}
return new TypedArray((V8TypedArray) value);
case V8Value.V8_ARRAY:
V8Array array = object.getArray(key);
try {
return toList(array, cache);
} finally {
if (array instanceof V8Array) {
array.release();
}
}
return toList((V8Array) value, cache, adapter);
case V8Value.V8_OBJECT:
V8Object child = object.getObject(key);
try {
return toMap(child, cache);
} finally {
if (child instanceof V8Object) {
child.release();
}
}
return toMap((V8Object) value, cache, adapter);
case V8Value.NULL:
return null;
case V8Value.UNDEFINED:
return V8.getUndefined();
default:
throw new IllegalStateException("Cannot find type for key: " + key);
throw new IllegalStateException("Cannot convert type " + V8Value.getStringRepresentation(valueType));
}
}
@ -626,6 +673,13 @@ public class V8ObjectUtils {
}
static class DefaultTypeAdapter implements TypeAdapter {
@Override
public Object adapt(final int type, final Object value) {
return TypeAdapter.DEFAULT;
}
}
static class ListWrapper {
private List<? extends Object> list;

4
fine-j2v8/src/com/eclipsesource/v8/utils/V8PropertyMap.java

@ -20,7 +20,7 @@ import java.util.Set;
/**
* A custom map is needed because the existing HashMaps
* do not self containment, and Hashtables do not
* do not allow self containment, and Hashtables do not
* allow nulls as values.
*
* This class is not considered API.
@ -166,7 +166,7 @@ class V8PropertyMap<V> implements Map<String, V> {
*/
@Override
public Set<Entry<String, V>> entrySet() {
HashSet<Entry<String, V>> result = new HashSet<Entry<String, V>>(map.entrySet());
HashSet<Entry<String, V>> result = new HashSet<Map.Entry<String, V>>(map.entrySet());
for (String nullKey : nulls) {
result.add(new SimpleEntry<String, V>(nullKey, null));
}

2
fine-j2v8/src/com/eclipsesource/v8/utils/V8Thread.java

@ -47,7 +47,7 @@ public class V8Thread extends Thread {
} finally {
synchronized (this) {
if (runtime.getLocker().hasLock()) {
runtime.release();
runtime.close();
runtime = null;
}
}

109
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java

@ -1,109 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
/**
* A wrapper class for java.nio.ByteBuffer. This class provides some convenience methods
* for working with the ByteBuffer. Furthermore, this class can be converted to a
* V8ByteBuffer using V8ObjectUtils.
*/
public class ArrayBuffer {
private ByteBuffer byteBuffer;
/**
* Create a new ArrayBuffer with an initial capacity.
*
* @param capacity The capacity of this ByteBuffer.
*/
public ArrayBuffer(final int capacity) {
byteBuffer = ByteBuffer.allocateDirect(capacity);
}
/**
* Create a new ArrayBuffer from a byte array. The array buffer will be allocated with the same
* size as the byte array, and the contents of the byte array will be copied to the ArrayBuffer.
*
* @param src The byte array from which the ArrayBuffer will be initialized.
*/
public ArrayBuffer(final byte[] src) {
byteBuffer = ByteBuffer.allocateDirect(src.length);
byteBuffer.put(src, 0, src.length);
}
/**
* Create a new ArrayBuffer with the given ByteBuffer as the backing store. The ByteBuffer must
* be created as a DirectBuffer.
*
* @param byteBuffer The ByteBuffer to back this ArrayBuffer.
*/
public ArrayBuffer(final ByteBuffer byteBuffer) {
this.byteBuffer = validateByteBuffer(byteBuffer);
}
private ByteBuffer validateByteBuffer(final ByteBuffer byteBuffer) {
if (!byteBuffer.isDirect()) {
throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer");
}
return byteBuffer;
}
/**
* Returns the ByteBuffer backing this ArrayBuffer.
*
* @return The ByteBuffer backing this ArrayBuffer.
*/
public ByteBuffer getByteBuffer() {
return byteBuffer;
}
/**
* Returns the byte at a given index.
*
* @param index The index at which to return the byte.
* @return The byte at the given index.
*/
public byte getByte(final int index) {
return byteBuffer.get(index);
}
/**
* Returns the byte at a given index as an unsigned integer.
*
* @param index The index at which to return the byte.
* @return The unsigned byte at the given index.
*/
public short getUnsignedByte(final int index) {
return (short) (0xFF & byteBuffer.get(index));
}
/**
* Puts a byte into the ByteBuffer at the given index.
*
* @param index The index at which to put the byte.
* @param value The value to put at the index.
*/
public void put(final int index, final byte value) {
byteBuffer.put(index, value);
}
/**
* Returns this ArrayBuffers limit.
*
* @return This ArrayBuffers limit.
*/
public int limit() {
return byteBuffer.limit();
}
}

79
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Float32Array.java

@ -1,79 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Float32Array typed array represents an array of 32-bit floating
* point numbers.
*/
public class Float32Array extends TypedArray {
/**
* Creates a Float32Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public Float32Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a Float32Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public Float32Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the floating point (Float32) value at a given index.
*
* @param index The index at which to return the value.
* @return The Float32 value at the given index.
*/
public float get(final int index) {
return buffer.asFloatBuffer().get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.asFloatBuffer().limit();
}
/**
* Puts a Float32 value at a particular index.
*
* @param index The index at which to place the value.
* @param value The Float32 value to place into buffer.
*/
public void put(final int index, final float value) {
buffer.asFloatBuffer().put(index, value);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.FLOAT_32_ARRAY;
}
}

79
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Float64Array.java

@ -1,79 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Float64Array typed array represents an array of 64-bit floating
* point numbers.
*/
public class Float64Array extends TypedArray {
/**
* Creates a Float64Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public Float64Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a Float64Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public Float64Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the floating point (Float64) value at a given index.
*
* @param index The index at which to return the value.
* @return The Double (Float64) value at the given index.
*/
public double get(final int index) {
return buffer.asDoubleBuffer().get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.asDoubleBuffer().limit();
}
/**
* Puts a Double (Float64) value at a particular index.
*
* @param index The index at which to place the value.
* @param value The Double to put into the buffer.
*/
public void put(final int index, final double value) {
buffer.asDoubleBuffer().put(index, value);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.FLOAT_64_ARRAY;
}
}

79
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int16Array.java

@ -1,79 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Int16Array typed array represents an array of twos-complement
* 16-bit signed integers in the platform byte order.
*/
public class Int16Array extends TypedArray {
/**
* Creates an Int16Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public Int16Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a Int16Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public Int16Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 16-bit signed integer at the given index
*
* @param index The index at which to return the value.
* @return The 16-bit integer at the index.
*/
public short get(final int index) {
return buffer.asShortBuffer().get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.asShortBuffer().limit();
}
/**
* Puts a 16-bit integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 16-bit integer to put into buffer.
*/
public void put(final int index, final short value) {
buffer.asShortBuffer().put(index, value);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.INT_16_ARRAY;
}
}

75
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int32Array.java

@ -1,75 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Int32Array typed array represents an array of twos-complement 32-bit signed
* integers in the platform byte order.
*/
public class Int32Array extends TypedArray {
/**
* Creates an Int32Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public Int32Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a Int32Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public Int32Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 32-bit signed integer at the given index.
*
* @param index The index at which to return the value.
* @return The 32-bit integer at the index.
*/
public int get(final int index) {
return buffer.asIntBuffer().get(index);
}
@Override
public int length() {
return buffer.asIntBuffer().limit();
}
/**
* Puts a 32-bit integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 32-bit integer to put into buffer.
*/
public void put(final int index, final int value) {
buffer.asIntBuffer().put(index, value);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.INT_32_ARRAY;
}
}

78
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/Int8Array.java

@ -1,78 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Int8Array typed array represents an array of twos-complement
* 8-bit signed integers.
*/
public class Int8Array extends TypedArray {
/**
* Creates an Int8Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public Int8Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a Int8Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public Int8Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 8-bit signed integer at the given index.
*
* @param index The index at which to return the value.
* @return The 8-bit integer at the index.
*/
public byte get(final int index) {
return buffer.get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.limit();
}
/**
* Puts an 8-bit integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 8-bit integer to put into buffer.
*/
public void put(final int index, final byte value) {
buffer.put(index, value);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.INT_8_ARRAY;
}
}

58
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/TypedArray.java

@ -1,58 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8TypedArray;
/**
* An abstract class that represents TypedArrays
*/
public abstract class TypedArray {
protected ByteBuffer buffer;
protected TypedArray(final ByteBuffer buffer) {
if (!buffer.isDirect()) {
throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer");
}
if ((buffer.limit() % V8TypedArray.getStructureSize(getType())) != 0) {
throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer");
}
this.buffer = buffer;
}
/**
* Return the underlying ByteBuffer.
*
* @return The underlying ByteBuffer behind this view
*/
public ByteBuffer getByteBuffer() {
return buffer;
}
/**
* Return the size of this view. The size of the view is determined by the size
* of the buffer, and the size of the data projected onto it. For example, for a
* buffer size of 8, and a view representing 16bit integers, the size would be 4.
*
* @return The size of this view
*/
public abstract int length();
/**
* Returns the 'Type' of this TypedArray using one of the constants defined in V8Value.
*
* @return The 'Type' of this typed array.
*/
public abstract int getType();
}

79
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java

@ -1,79 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Uint16Array typed array represents an array of 16-bit unsigned
* integers in the platform byte order.
*/
public class UInt16Array extends TypedArray {
/**
* Creates an UInt16Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public UInt16Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a UInt16Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public UInt16Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 16-bit unsigned integer at the given index.
*
* @param index The index at which to return the value.
* @return The 16-bit unsigned integer at the index.
*/
public int get(final int index) {
return 0xFFFF & buffer.asShortBuffer().get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.asShortBuffer().limit();
}
/**
* Puts a 16-bit unsigned integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 16-bit unsigned integer to put into buffer.
*/
public void put(final int index, final int value) {
buffer.asShortBuffer().put(index, (short) (0x0000FFFF & value));
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.UNSIGNED_INT_16_ARRAY;
}
}

79
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java

@ -1,79 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Uint32Array typed array represents an array of 32-bit unsigned
* integers in the platform byte order.
*/
public class UInt32Array extends TypedArray {
/**
* Creates an UInt32Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public UInt32Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a UInt32Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public UInt32Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 32-bit unsigned integer at the given index.
*
* @param index The index at which to return the value.
* @return The 32-bit unsigned integer at the index.
*/
public long get(final int index) {
return 0x00000000FFFFFFFF & buffer.asIntBuffer().get(index);
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.asIntBuffer().limit();
}
/**
* Puts a 32-bit unsigned integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 32-bit unsigned integer to put into buffer.
*/
public void put(final int index, final long value) {
buffer.asIntBuffer().put(index, (int) (0x00000000FFFFFFFF & value));
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.UNSIGNED_INT_32_ARRAY;
}
}

78
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java

@ -1,78 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Uint8Array typed array represents an array of 8-bit unsigned integers
*/
public class UInt8Array extends TypedArray {
/**
* Creates an UInt8Array projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public UInt8Array(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a UInt8Array projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public UInt8Array(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 8-bit unsigned integer at the given index.
*
* @param index The index at which to return the value.
* @return The 8-bit unsigned integer at the index.
*/
public short get(final int index) {
return (short) (0xFF & buffer.get(index));
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.limit();
}
/**
* Puts a 8-bit unsigned integer at a particular index.
*
* @param index The index at which to place the value.
* @param value The 8-bit unsigned integer to put into buffer.
*/
public void put(final int index, final short value) {
buffer.put(index, (byte) (0x00FF & value));
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.UNSIGNED_INT_8_ARRAY;
}
}

87
fine-j2v8/src/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.v8.utils.typedarrays;
import java.nio.ByteBuffer;
import com.eclipsesource.v8.V8Value;
/**
* The Uint8ClampedArray typed array represents an array of 8-bit unsigned
* integers clamped to 0-255; if you specified a value that is out of the
* range of [0,255], 0 or 255 will be set instead.
*/
public class UInt8ClampedArray extends TypedArray {
/**
* Creates an UInt8ClampedArray projected onto the given ByteBuffer.
*
* @param buffer The ByteBuffer on which the array is projected on.
*/
public UInt8ClampedArray(final ByteBuffer buffer) {
super(buffer);
}
/**
* Creates a UInt8ClampedArray projected onto the given ArrayBuffer.
*
* @param arrayBuffer The ArrayBuffer on which the array is projected on.
*/
public UInt8ClampedArray(final ArrayBuffer arrayBuffer) {
this(arrayBuffer.getByteBuffer());
}
/**
* Returns the 8-bit unsigned integer at the given index.
*
* @param index The index at which to return the value.
* @return The 8-bit unsigned integer at the index.
*/
public short get(final int index) {
return (short) (0xFF & buffer.get(index));
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length()
*/
@Override
public int length() {
return buffer.limit();
}
/**
* Puts a 8-bit unsigned integer at a particular index. If the unsigned
* integer is outside the range [0,255], 0 or 255 will be used instead.
*
* @param index The index at which to place the value.
* @param value The 8-bit unsigned integer to put into buffer.
*/
public void put(final int index, final short value) {
if (value > 255) {
buffer.put(index, (byte) (255));
} else if (value < 0) {
buffer.put(index, (byte) (0));
} else {
buffer.put(index, (byte) (value));
}
}
/*
* (non-Javadoc)
* @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType()
*/
@Override
public int getType() {
return V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY;
}
}

BIN
fine-j2v8/src/libj2v8_linux_x86_64.so → fine-j2v8/src/libj2v8-linux-x86_64.so

Binary file not shown.

BIN
fine-j2v8/src/libj2v8_macosx_x86_64.dylib → fine-j2v8/src/libj2v8-macosx-x86_64.dylib

Binary file not shown.

BIN
fine-j2v8/src/libj2v8_win32_x86_64.dll → fine-j2v8/src/libj2v8-windows-x86_64.dll

Binary file not shown.
Loading…
Cancel
Save