diff --git a/build.third_step1-jdk11.gradle b/build.third_step1-jdk11.gradle
index f732d6699..3de001b14 100644
--- a/build.third_step1-jdk11.gradle
+++ b/build.third_step1-jdk11.gradle
@@ -43,6 +43,7 @@ sourceSets{
"${srcDir}/fine-hsqldb/src/main/java",
"${srcDir}/fine-iconloader/src/main/java",
"${srcDir}/fine-icu4j/src/main/java",
+ "${srcDir}/fine-j2v8/src/main/java",
// "${srcDir}/fine-jai/src/main/java",
"${srcDir}/fine-jboss-transaction-api/src/main/java",
"${srcDir}/fine-jgit/src/main/java",
@@ -95,6 +96,8 @@ def resourceDirs = [
"${srcDir}/fine-iconloader/src/main/resources",
"${srcDir}/fine-icu4j/src/main/java",
"${srcDir}/fine-icu4j/src/main/resources",
+ "${srcDir}/fine-j2v8/src/main/java",
+ "${srcDir}/fine-j2v8/src/main/resources",
// "${srcDir}/fine-jai/src/main/java",
"${srcDir}/fine-jboss-transaction-api/src/main/java",
"${srcDir}/fine-jboss-transaction-api/src/main/resources",
diff --git a/build.third_step1.gradle b/build.third_step1.gradle
index 944ee24e5..403fa3c01 100644
--- a/build.third_step1.gradle
+++ b/build.third_step1.gradle
@@ -44,6 +44,7 @@ sourceSets{
"${srcDir}/fine-hsqldb/src/main/java",
"${srcDir}/fine-iconloader/src/main/java",
"${srcDir}/fine-icu4j/src/main/java",
+ "${srcDir}/fine-j2v8/src/main/java",
// "${srcDir}/fine-jai/src/main/java",
"${srcDir}/fine-jboss-transaction-api/src/main/java",
"${srcDir}/fine-jgit/src/main/java",
@@ -68,7 +69,8 @@ sourceSets{
"${srcDir}/fine-third-jdk11/fine-javax-jws/src/main/java",
"${srcDir}/fine-third-jdk11/fine-javax-xml-soap/src/main/java",
"${srcDir}/fine-third-jdk11/fine-jaxb/src/main/java",
- "${srcDir}/fine-third-jdk11/fine-jaxws/src/main/java"
+ "${srcDir}/fine-third-jdk11/fine-jaxws/src/main/java",
+ "${srcDir}/fine-skywalking-toolkit-trace/src/main/java"
]
}
}
@@ -143,6 +145,8 @@ task copyFiles(type:Copy,dependsOn:'compileJava'){
with dataContent.call("${srcDir}/fine-hsqldb/src/main/resources")
with dataContent.call("${srcDir}/fine-icu4j/src/main/java")
with dataContent.call("${srcDir}/fine-icu4j/src/main/resources")
+ with dataContent.call("${srcDir}/fine-j2v8/src/main/java")
+ with dataContent.call("${srcDir}/fine-j2v8/src/main/resources")
// with dataContent.call("${srcDir}/fine-jai/src/main/java")
with dataContent.call("${srcDir}/fine-jboss-transaction-api/src/main/java")
with dataContent.call("${srcDir}/fine-jboss-transaction-api/src/main/resources")
@@ -167,6 +171,7 @@ task copyFiles(type:Copy,dependsOn:'compileJava'){
with dataContent.call("${srcDir}/fine-sense4/src/main/resources")
with dataContent.call("${srcDir}/fine-netty/src/main/java")
with dataContent.call("${srcDir}/fine-netty/src/main/resources")
+ with dataContent.call("${srcDir}/fine-skywalking-toolkit-trace/src/main/java")
with dataContent.call("${srcDir}/fine-third-default/fine-sun-misc/src/main/java")
with dataContent.call("${srcDir}/fine-third-default/fine-zip-tools/src/main/java")
with dataContent.call("${srcDir}/fine-third-default/fine-sun-jpeg/src/main/java")
diff --git a/fine-druid/src/main/java/com/fr/third/alibaba/druid/util/MySqlUtils.java b/fine-druid/src/main/java/com/fr/third/alibaba/druid/util/MySqlUtils.java
index c5523d370..bdaa15baa 100644
--- a/fine-druid/src/main/java/com/fr/third/alibaba/druid/util/MySqlUtils.java
+++ b/fine-druid/src/main/java/com/fr/third/alibaba/druid/util/MySqlUtils.java
@@ -16,6 +16,7 @@
package com.fr.third.alibaba.druid.util;
import com.fr.third.alibaba.druid.DbType;
+import com.fr.third.alibaba.druid.proxy.jdbc.ConnectionProxy;
import com.fr.third.alibaba.druid.sql.SQLUtils;
import com.fr.third.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
@@ -403,8 +404,13 @@ public class MySqlUtils {
}
public static long getLastPacketReceivedTimeMs(Connection conn) throws SQLException {
-
- ClassLoader cl = conn.getClass().getClassLoader();
+ // durid监控若开启,Connection 对象是 ConnectionProxy ,且ConnectionProxy和Connection不一定在同一个类加载器下
+ ClassLoader cl;
+ if (conn instanceof ConnectionProxy) {
+ cl = ((ConnectionProxy) conn).getRawObject().getClass().getClassLoader();
+ } else {
+ cl = conn.getClass().getClassLoader();
+ }
ConnectionClass cc = classLoaderConnectionClassMap.compute(cl, (k, v) -> {
if (v == null || v.class_connectionImpl.getClassLoader() != cl) {
return new ConnectionClass();
diff --git a/fine-j2v8/pom.xml b/fine-j2v8/pom.xml
new file mode 100644
index 000000000..72cbb4efa
--- /dev/null
+++ b/fine-j2v8/pom.xml
@@ -0,0 +1,18 @@
+
+
+ 4.0.0
+
+
+ com.fr.third
+ step1
+ ${revision}
+ ../base-third-project/base-third-step1
+
+
+ fine-j2v8
+ ${revision}
+
+
+
\ No newline at end of file
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaCallback.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaCallback.java
new file mode 100644
index 000000000..2bf5a19b3
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaCallback.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * Classes that implement this interface provide a method
+ * which can be invoked from JavaScript. The method can return
+ * a result.
+ *
+ * After creating an instance of a class that implements this
+ * interface it can be registered as a Callback on a V8Object.
+ */
+public interface JavaCallback {
+
+ /**
+ * Called when a JS Function invokes a the registered Java
+ * method.
+ *
+ * @param receiver The V8Object that the function was called on.
+ * @param parameters The parameters passed to the JS Function. The
+ * parameter array does not need to be released, by any objects accessed
+ * from the array must be.
+ *
+ * @return A result that should be passed back to JavaScript. The
+ * result must be either an Integer, Double, Boolean, String or V8Value.
+ */
+ public Object invoke(V8Object receiver, V8Array parameters);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaVoidCallback.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaVoidCallback.java
new file mode 100644
index 000000000..7298d5a40
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/JavaVoidCallback.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * Classes that implement this interface provide a method
+ * which can be invoked from JavaScript.
+ *
+ * After creating an instance of a class that implements this
+ * interface it can be registered as a Callback on a V8Object.
+ */
+public interface JavaVoidCallback {
+
+ /**
+ * Called when a JS Function invokes a the registered Java
+ * method.
+ *
+ * @param receiver The V8Object that the function was called on.
+ * @param parameters The parameters passed to the JS Function. The
+ * parameter array does not need to be released, by any objects accessed
+ * from the array must be.
+ */
+ public void invoke(V8Object receiver, V8Array parameters);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/LibraryLoader.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/LibraryLoader.java
new file mode 100644
index 000000000..741b8bd3a
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/LibraryLoader.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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
+ * Wolfgang Steiner - code separation PlatformDetector/LibraryLoader
+ ******************************************************************************/
+package com.eclipsesource.v8;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class LibraryLoader {
+
+ static final String SEPARATOR;
+ static final String DELIMITER;
+
+ static final String SWT_LIB_DIR = ".j2v8";
+
+ static {
+ DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
+ SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the base-name for the native J2V8 library file.
+ * @param withLinuxVendor include/exclude the {vendor} part from the returned filename
+ * NOTE: Vendors are only included for linux systems
+ * @return The filename string has the following structure:
+ * {arch}-[vendor]-{operating_system}
+ */
+ 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 = "-";
+
+ return
+ prefix +
+ (vendor != null ? separator + vendor : "") +
+ separator + os +
+ separator + arch;
+ }
+
+ public static String computeLibraryFullName(boolean withLinuxVendor) {
+ return "lib" + computeLibraryShortName(withLinuxVendor) + "." + PlatformDetector.OS.getLibFileExtension();
+ }
+
+ 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 true;
+ }
+
+ /* Try loading library from the IDE location */
+ if (new File(ideLocation).exists()) {
+ if (load(ideLocation, message)) {
+ 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("java.io.tmpdir"); //$NON-NLS-1$
+ }
+
+ // 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$
+ }
+
+ static boolean load(final String libName, final StringBuffer message) {
+ try {
+ if (libName.indexOf(SEPARATOR) != -1) {
+ System.load(libName);
+ } else {
+ System.loadLibrary(libName);
+ }
+ return true;
+ } catch (UnsatisfiedLinkError e) {
+ if (message.length() == 0) {
+ message.append(DELIMITER);
+ }
+ message.append('\t');
+ message.append(e.getMessage());
+ message.append(DELIMITER);
+ }
+ 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);
+ boolean extracted = false;
+ try {
+ if (file.exists()) {
+ file.delete();
+ }
+ is = LibraryLoader.class.getResourceAsStream("/" + mappedName); //$NON-NLS-1$
+ if (is != null) {
+ extracted = true;
+ int read;
+ byte[] buffer = new byte[4096];
+ os = new FileOutputStream(fileName);
+ while ((read = is.read(buffer)) != -1) {
+ os.write(buffer, 0, read);
+ }
+ os.close();
+ is.close();
+ chmod("755", fileName);
+ if (load(fileName, message)) {
+ return true;
+ }
+ }
+ } catch (Throwable e) {
+ try {
+ if (os != null) {
+ os.close();
+ }
+ } catch (IOException e1) {
+ }
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e1) {
+ }
+ if (extracted && file.exists()) {
+ file.delete();
+ }
+ }
+ return false;
+ }
+
+ static void chmod(final String permision, final String path) {
+ if (PlatformDetector.OS.isWindows()) {
+ return;
+ }
+ try {
+ Runtime.getRuntime().exec(new String[] { "chmod", permision, path }).waitFor(); //$NON-NLS-1$
+ } catch (Throwable e) {
+ }
+ }
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/Platform.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/Platform.java
new file mode 100644
index 000000000..8168935bc
--- /dev/null
+++ b/fine-j2v8/src/main/java/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";
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java
new file mode 100644
index 000000000..0913c1a69
--- /dev/null
+++ b/fine-j2v8/src/main/java/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)$") || value.startsWith("armv7")) {
+ return "arm_32";
+ }
+ if ("aarch64".equals(value) || value.startsWith("armv8")) {
+ 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]+", "");
+ }
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/ReferenceHandler.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/ReferenceHandler.java
new file mode 100644
index 000000000..740dc18ee
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/ReferenceHandler.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Callback used to track when native handles are created and released.
+ */
+public interface ReferenceHandler {
+
+ /**
+ * Called when a native handle is first created. The V8Value
+ * referenced by that handle is passed as a parameter.
+ *
+ * @param object The V8Value referenced by the handle
+ */
+ public void v8HandleCreated(V8Value object);
+
+ /**
+ * Called when a native handle is released. The V8Value
+ * referenced by that handle is passed as a parameter.
+ *
+ * @param object The V8Value referenced by the handle
+ */
+ public void v8HandleDisposed(V8Value object);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/Releasable.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/Releasable.java
new file mode 100644
index 000000000..3edee1e61
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/Releasable.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import java.io.Closeable;
+
+/**
+ * An interface used to denote all V8 Classes which can be released.
+ */
+public interface Releasable extends Closeable {
+
+ /**
+ * Release the underlying resources. Once an object is released
+ * it typically cannot be used again.
+ */
+ void close();
+
+ /**
+ * Synonym for {@link #close()}.
+ */
+ void release();
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java
new file mode 100644
index 000000000..035c5b06b
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java
@@ -0,0 +1,5 @@
+package com.eclipsesource.v8;
+
+public interface SignatureProvider {
+ public byte[] getSignature(String uri);
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java
new file mode 100644
index 000000000..abaec598c
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java
@@ -0,0 +1,1666 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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
+ * on a single runtime, and data is not shared between runtimes.
+ * A runtime must be created and released when finished.
+ *
+ * All access to a runtime must come from the same thread, unless
+ * the thread explicitly gives up control using the V8Locker.
+ *
+ * A public static factory method can be used to create the runtime.
+ *
+ * V8 runtime = V8.createV8Runtime();
+ */
+public class V8 extends V8Object {
+
+ private static Object lock = new Object();
+ private volatile static int runtimeCounter = 0;
+ private static String v8Flags = null;
+ private static boolean initialized = false;
+ protected Map v8WeakReferences = new HashMap();
+
+ private Map data = null;
+ private final V8Locker locker;
+ private SignatureProvider signatureProvider = null;
+ private long objectReferences = 0;
+ private long v8RuntimePtr = 0;
+ private List resources = null;
+ private V8Map executors = null;
+ private boolean forceTerminateExecutors = false;
+ private Map functionRegistry = new HashMap();
+ private LinkedList referenceHandlers = new LinkedList();
+ private LinkedList releaseHandlers = new LinkedList();
+
+ private static boolean nativeLibraryLoaded = false;
+ private static Error nativeLoadError = null;
+ private static Exception nativeLoadException = null;
+ private static V8Value undefined = new Undefined();
+ private static Object invalid = new Object();
+
+ private class MethodDescriptor {
+ Object object;
+ Method method;
+ JavaCallback callback;
+ JavaVoidCallback voidCallback;
+ boolean includeReceiver;
+ }
+
+ private synchronized static void load(final String tmpDirectory) {
+ try {
+ LibraryLoader.loadLibrary(tmpDirectory);
+ nativeLibraryLoaded = true;
+ } catch (Error e) {
+ nativeLoadError = e;
+ } catch (Exception e) {
+ nativeLoadException = e;
+ }
+ }
+
+ /**
+ * Determines if the native libraries are loaded.
+ *
+ * @return Returns true if the native libraries are loaded,
+ * false otherwise.
+ */
+ public static boolean isLoaded() {
+ return nativeLibraryLoaded;
+ }
+
+ /**
+ * Sets the V8 flags on the platform. All runtimes will be created
+ * with the same flags. Flags must be set before the runtime is
+ * created.
+ *
+ * @param flags The flags to set on V8
+ */
+ public static void setFlags(final String flags) {
+ v8Flags = flags;
+ initialized = false;
+ }
+
+ /**
+ * Creates a new V8Runtime and loads the required
+ * native libraries if they are not already loaded.
+ * The current thread is given the lock to this runtime.
+ *
+ * @return A new isolated V8 Runtime.
+ */
+ public static V8 createV8Runtime() {
+ return createV8Runtime(null, null);
+ }
+
+ /**
+ * Creates a new V8Runtime and loads the required native libraries if they
+ * are not already loaded. An alias is also set for the global scope. For example,
+ * 'window' can be set as the global scope name.
+ *
+ * The current thread is given the lock to this runtime.
+ *
+ * @param globalAlias The name to associate with the global scope.
+ * @return A new isolated V8 Runtime.
+ */
+ public static V8 createV8Runtime(final String globalAlias) {
+ return createV8Runtime(globalAlias, null);
+ }
+
+ /**
+ * Creates a new V8Runtime and loads the required native libraries if they
+ * are not already loaded. An alias is also set for the global scope. For example,
+ * 'window' can be set as the global scope name.
+ *
+ * The current thread is given the lock to this runtime.
+ *
+ * @param globalAlias The name to associate with the global scope.
+ * @param tempDirectory The name of the directory to extract the native
+ * libraries too.
+ * @return A new isolated V8 Runtime.
+ */
+ public static V8 createV8Runtime(final String globalAlias, final String tempDirectory) {
+ if (!nativeLibraryLoaded) {
+ synchronized (lock) {
+ if (!nativeLibraryLoaded) {
+ load(tempDirectory);
+ }
+ }
+ }
+ checkNativeLibraryLoaded();
+ if (!initialized) {
+ _setFlags(v8Flags);
+ initialized = true;
+ }
+ V8 runtime = new V8(globalAlias);
+ synchronized (lock) {
+ runtimeCounter++;
+ }
+ return runtime;
+ }
+
+ public void setSignatureProvider(final SignatureProvider signatureProvider) {
+ this.signatureProvider = signatureProvider;
+ }
+
+ /**
+ * Adds a ReferenceHandler to track when new V8Objects are created.
+ *
+ * @param handler The ReferenceHandler to add
+ */
+ public void addReferenceHandler(final ReferenceHandler handler) {
+ 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.
+ *
+ * @param handler The reference handler to remove
+ */
+ public void removeReferenceHandler(final ReferenceHandler handler) {
+ 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();
+ }
+ 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);
+ }
+ }
+
+ private void notifyReferenceDisposed(final V8Value object) {
+ for (ReferenceHandler referenceHandler : referenceHandlers) {
+ referenceHandler.v8HandleDisposed(object);
+ }
+ }
+
+ 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(message, nativeLoadError);
+ } else if (nativeLoadException != null) {
+ throw new IllegalStateException(message, nativeLoadException);
+ } else {
+ throw new IllegalStateException(message);
+ }
+ }
+ }
+
+ protected V8() {
+ this(null);
+ }
+
+ protected V8(final String globalAlias) {
+ super(null);
+ released = false;
+ v8RuntimePtr = _createIsolate(globalAlias);
+ locker = new V8Locker(this);
+ checkThread();
+ objectHandle = _getGlobalObject(v8RuntimePtr);
+ }
+
+// public void dispatchProtocolMessage(final long V8InspectorPtr, final String protocolMessage) {
+// checkThread();
+// _dispatchProtocolMessage(v8RuntimePtr, V8InspectorPtr, protocolMessage);
+// }
+
+// public void schedulePauseOnNextStatement(final long V8InspectorPtr, final String reason) {
+// checkThread();
+// _schedulePauseOnNextStatement(v8RuntimePtr, V8InspectorPtr, reason);
+// }
+
+ /**
+ * Returns an UNDEFINED constant.
+ *
+ * @return The UNDEFINED constant value.
+ */
+ public static V8Value getUndefined() {
+ return undefined;
+ }
+
+ /**
+ * Returns the number of active runtimes.
+ *
+ * @return The number of active runtimes.
+ */
+ public static int getActiveRuntimes() {
+ return runtimeCounter;
+ }
+
+ /**
+ * Returns the number of Object References for this runtime.
+ *
+ * @return The number of Object References on this runtime.
+ */
+ public long getObjectReferenceCount() {
+ return objectReferences - v8WeakReferences.size();
+ }
+
+ public long getV8RuntimePtr() {
+ return v8RuntimePtr;
+ }
+
+ /**
+ * Gets the version of the V8 engine
+ *
+ * @return The version of the V8 Engine.
+ */
+ public static String getV8Version() {
+ 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);
+ }
+
+ /**
+ * Terminates any JavaScript executing on this runtime. Once
+ * the runtime is released, any executors that were spawned
+ * will also be force terminated.
+ */
+ public void terminateExecution() {
+ forceTerminateExecutors = true;
+ terminateExecution(v8RuntimePtr);
+ }
+
+ /**
+ * Release native resources associated with this runtime. Once
+ * released, a runtime cannot be reused.
+ *
+ * @param reportMemoryLeaks True if memory leaks should be
+ * reported by throwing an IllegalStateException if any
+ * objects were not released.
+ */
+ public void release(final boolean reportMemoryLeaks) {
+ if (isReleased()) {
+ return;
+ }
+ checkThread();
+ try {
+ notifyReleaseHandlers(this);
+ } finally {
+ releaseResources();
+ shutdownExecutors(forceTerminateExecutors);
+ if (executors != null) {
+ executors.clear();
+ }
+ releaseNativeMethodDescriptors();
+ synchronized (lock) {
+ runtimeCounter--;
+ }
+ _releaseRuntime(v8RuntimePtr);
+ v8RuntimePtr = 0L;
+ released = true;
+ if (reportMemoryLeaks && (getObjectReferenceCount() > 0)) {
+ throw new IllegalStateException(getObjectReferenceCount() + " Object(s) still exist in runtime");
+ }
+ }
+ }
+
+ private void releaseNativeMethodDescriptors() {
+ Set nativeMethodDescriptors = functionRegistry.keySet();
+ for (Long nativeMethodDescriptor : nativeMethodDescriptors) {
+ releaseMethodDescriptor(v8RuntimePtr, nativeMethodDescriptor);
+ }
+ }
+
+ private void releaseResources() {
+ if (resources != null) {
+ for (Releasable releasable : resources) {
+ releasable.release();
+ }
+ resources.clear();
+ resources = null;
+ }
+ }
+
+ /**
+ * Registers an executor with this runtime. An executor is another
+ * runtime with its own thread. By registering an executor, it can be
+ * terminated when this runtime is released.
+ *
+ * @param key The key to associate the executor with.
+ * @param executor The executor itself.
+ */
+ public void registerV8Executor(final V8Object key, final V8Executor executor) {
+ checkThread();
+ if (executors == null) {
+ executors = new V8Map();
+ }
+ executors.put(key, executor);
+ }
+
+ /**
+ * Removes the executor from this runtime. The executor is
+ * *NOT* shutdown, simply removed from the list of known
+ * executors.
+ *
+ * @param key The key the executor was associated with.
+ * @return The executor or null if it does not exist.
+ */
+ public V8Executor removeExecutor(final V8Object key) {
+ checkThread();
+ if (executors == null) {
+ return null;
+ }
+ return executors.remove(key);
+ }
+
+ /**
+ * Returns the executor associated with the given key.
+ *
+ * @param key The key the executor was associated with.
+ * @return The executor or null if it does not exist.
+ */
+ public V8Executor getExecutor(final V8Object key) {
+ checkThread();
+ if (executors == null) {
+ return null;
+ }
+ return executors.get(key);
+ }
+
+ /**
+ * Shutdown all executors associated with this runtime.
+ * If force terminate is specified, it will forcefully terminate
+ * the executors, otherwise it will simply signal that they
+ * should terminate.
+ *
+ * @param forceTerminate Specify if the executors should be
+ * forcefully terminated, or simply notified to shutdown when ready.
+ */
+ public void shutdownExecutors(final boolean forceTerminate) {
+ checkThread();
+ if (executors == null) {
+ return;
+ }
+ for (V8Executor executor : executors.values()) {
+ if (forceTerminate) {
+ executor.forceTermination();
+ } else {
+ executor.shutdown();
+ }
+ }
+ }
+
+ /**
+ * Registers a resource with this runtime. All registered
+ * resources will be released before the runtime is released.
+ *
+ * @param resource The resource to register.
+ */
+ public void registerResource(final Releasable resource) {
+ checkThread();
+ if (resources == null) {
+ resources = new ArrayList();
+ }
+ resources.add(resource);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as an integer.
+ * If the result is not an integer, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as an integer, or V8ResultUndefinedException if
+ * the result is not an integer.
+ */
+ public int executeIntegerScript(final String script) {
+ return executeIntegerScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as an integer.
+ * If the result is not an integer, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for excepton purposes.
+ * @return The result of the script as an integer, or V8ResultUndefinedException if
+ * the result is not an integer.
+ */
+ public int executeIntegerScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ return executeIntegerScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ protected void createTwin(final V8Value value, final V8Value twin) {
+ checkThread();
+ createTwin(v8RuntimePtr, value.getHandle(), twin.getHandle());
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a double.
+ * If the result is not a double, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a double, or V8ResultUndefinedException if
+ * the result is not a double.
+ */
+ public double executeDoubleScript(final String script) {
+ return executeDoubleScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a double.
+ * If the result is not a double, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a double, or V8ResultUndefinedException if
+ * the result is not a double.
+ */
+ public double executeDoubleScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ return executeDoubleScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a String.
+ * If the result is not a String, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a String, or V8ResultUndefinedException if
+ * the result is not a String.
+ */
+ public String executeStringScript(final String script) {
+ return executeStringScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a String.
+ * If the result is not a String, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a String, or V8ResultUndefinedException if
+ * the result is not a String.
+ */
+ public String executeStringScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ return executeStringScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a boolean.
+ * If the result is not a boolean, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a boolean, or V8ResultUndefinedException if
+ * the result is not a boolean.
+ */
+ public boolean executeBooleanScript(final String script) {
+ return executeBooleanScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a boolean.
+ * If the result is not a boolean, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a boolean, or V8ResultUndefinedException if
+ * the result is not a boolean.
+ */
+ public boolean executeBooleanScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ return executeBooleanScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a V8Array.
+ * If the result is not a V8Array, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a V8Array, or V8ResultUndefinedException if
+ * the result is not a V8Array.
+ */
+ public V8Array executeArrayScript(final String script) {
+ return executeArrayScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a V8Array.
+ * If the result is not a V8Array, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a V8Array, or V8ResultUndefinedException if
+ * the result is not a V8Array.
+ */
+ public V8Array executeArrayScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ Object result = this.executeScript(script, scriptName, lineNumber);
+ if (result instanceof V8Array) {
+ return (V8Array) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a Java Object.
+ * Primitives will be boxed.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a Java Object.
+ */
+ public Object executeScript(final String script) {
+ return executeScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a Java Object.
+ * Primitives will be boxed.
+ *
+ * @param script The script to execute.
+ * @param uri The name of the script
+ * @return The result of the script as a Java Object.
+ */
+ public Object executeScript(final String script, final String uri) {
+ checkThread();
+ checkScript(script);
+ return executeScript(getV8RuntimePtr(), UNKNOWN, script, uri, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a Java Object.
+ * Primitives will be boxed.
+ *
+ * @param script The script to execute.
+ * @param uri The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a Java Object.
+ */
+ public Object executeScript(final String script, final String uri, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ return executeScript(getV8RuntimePtr(), UNKNOWN, script, uri, lineNumber);
+ }
+
+ /**
+ * Executes a JS Script module on this runtime and returns the result as a Java Object.
+ * Primitives will be boxed.
+ *
+ * If the script does not match the signature (as verified with the public key) then a
+ * V8SecurityException will be thrown.
+ *
+ * @param script The signed script to execute
+ * @param modulePrefix The module prefix
+ * @param modulePostfix The module postfix
+ * @param uri The name of the script
+ * @return The result of the script as a Java Object.
+ */
+ public Object executeModule(final String script, final String modulePrefix, final String modulePostfix, final String uri) {
+ checkThread();
+ checkScript(script);
+ return executeScript(getV8RuntimePtr(), UNKNOWN, modulePrefix + script + modulePostfix, uri, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a V8Object.
+ * If the result is not a V8Object, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @return The result of the script as a V8Object, or V8ResultUndefinedException if
+ * the result is not a V8Object.
+ */
+ public V8Object executeObjectScript(final String script) {
+ return this.executeObjectScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime and returns the result as a V8Object.
+ * If the result is not a V8Object, then a V8ResultUndefinedException is thrown.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ * @return The result of the script as a V8Object, or V8ResultUndefinedException if
+ * the result is not a V8Object.
+ */
+ public V8Object executeObjectScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ Object result = this.executeScript(script, scriptName, lineNumber);
+ if (result instanceof V8Object) {
+ return (V8Object) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Executes a JS Script on this runtime.
+ *
+ * @param script The script to execute.
+ */
+ public void executeVoidScript(final String script) {
+ executeVoidScript(script, null, 0);
+ }
+
+ /**
+ * Executes a JS Script on this runtime.
+ *
+ * @param script The script to execute.
+ * @param scriptName The name of the script
+ * @param lineNumber The line number that is considered to be the first line of
+ * the script. Typically 0, but could be set to another value for exception stack trace purposes.
+ */
+ public void executeVoidScript(final String script, final String scriptName, final int lineNumber) {
+ checkThread();
+ checkScript(script);
+ executeVoidScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ /**
+ * Returns the locker associated with this runtime. The locker allows
+ * threads to give up control of the runtime and other threads to acquire
+ * control.
+ *
+ * @return The locker associated with this runtime.
+ */
+ public V8Locker getLocker() {
+ return locker;
+ }
+
+ /**
+ * Returns the unique build ID of the native library.
+ *
+ * @return The unique build ID of the Native library.
+ */
+ public static long getBuildID() {
+ 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()) {
+ throw new Error("Runtime disposed error");
+ }
+ }
+
+ static void checkScript(final String script) {
+ if (script == null) {
+ throw new NullPointerException("Script is null");
+ }
+ }
+
+ void registerCallback(final Object object, final Method method, final long objectHandle, final String jsFunctionName, final boolean includeReceiver) {
+ MethodDescriptor methodDescriptor = new MethodDescriptor();
+ methodDescriptor.object = object;
+ methodDescriptor.method = method;
+ methodDescriptor.includeReceiver = includeReceiver;
+ long methodID = registerJavaMethod(getV8RuntimePtr(), objectHandle, jsFunctionName, isVoidMethod(method));
+ functionRegistry.put(methodID, methodDescriptor);
+ }
+
+ void registerVoidCallback(final JavaVoidCallback callback, final long objectHandle, final String jsFunctionName) {
+ MethodDescriptor methodDescriptor = new MethodDescriptor();
+ methodDescriptor.voidCallback = callback;
+ long methodID = registerJavaMethod(getV8RuntimePtr(), objectHandle, jsFunctionName, true);
+ functionRegistry.put(methodID, methodDescriptor);
+ }
+
+ void registerCallback(final JavaCallback callback, final long objectHandle, final String jsFunctionName) {
+ long methodID = registerJavaMethod(getV8RuntimePtr(), objectHandle, jsFunctionName, false);
+ createAndRegisterMethodDescriptor(callback, methodID);
+ }
+
+ void createAndRegisterMethodDescriptor(final JavaCallback callback, final long methodID) {
+ MethodDescriptor methodDescriptor = new MethodDescriptor();
+ methodDescriptor.callback = callback;
+ functionRegistry.put(methodID, methodDescriptor);
+ }
+
+ private boolean isVoidMethod(final Method method) {
+ Class> returnType = method.getReturnType();
+ if (returnType.equals(Void.TYPE)) {
+ return true;
+ }
+ return false;
+ }
+
+ private Object getDefaultValue(final Class> type) {
+ if (type.equals(V8Object.class)) {
+ return new Undefined();
+ } else if (type.equals(V8Array.class)) {
+ return new V8Array.Undefined();
+ }
+ return invalid;
+ }
+
+ protected void disposeMethodID(final long methodID) {
+ 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) {
+ return checkResult(methodDescriptor.callback.invoke(receiver, parameters));
+ }
+ boolean hasVarArgs = methodDescriptor.method.isVarArgs();
+ Object[] args = getArgs(receiver, methodDescriptor, parameters, hasVarArgs);
+ checkArgs(args);
+ try {
+ Object result = methodDescriptor.method.invoke(methodDescriptor.object, args);
+ return checkResult(result);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ } catch (IllegalAccessException e) {
+ throw e;
+ } catch (IllegalArgumentException e) {
+ throw e;
+ } finally {
+ releaseArguments(args, hasVarArgs);
+ }
+ }
+
+ private Object checkResult(final Object result) {
+ if (result == null) {
+ return result;
+ }
+ if (result instanceof Float) {
+ return ((Float) result).doubleValue();
+ }
+ if ((result instanceof Integer) || (result instanceof Double) || (result instanceof Boolean)
+ || (result instanceof String)) {
+ return result;
+ }
+ if (result instanceof V8Value) {
+ if (((V8Value) result).isReleased()) {
+ throw new V8RuntimeException("V8Value already released");
+ }
+ return result;
+ }
+ throw new V8RuntimeException("Unknown return type: " + result.getClass());
+ }
+
+ protected void callVoidJavaMethod(final long methodID, final V8Object receiver, final V8Array parameters) throws Throwable {
+ MethodDescriptor methodDescriptor = functionRegistry.get(methodID);
+ if (methodDescriptor.voidCallback != null) {
+ methodDescriptor.voidCallback.invoke(receiver, parameters);
+ return;
+ }
+ boolean hasVarArgs = methodDescriptor.method.isVarArgs();
+ Object[] args = getArgs(receiver, methodDescriptor, parameters, hasVarArgs);
+ checkArgs(args);
+ try {
+ methodDescriptor.method.invoke(methodDescriptor.object, args);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ } catch (IllegalAccessException e) {
+ throw e;
+ } catch (IllegalArgumentException e) {
+ throw e;
+ } finally {
+ releaseArguments(args, hasVarArgs);
+ }
+ }
+
+ private void checkArgs(final Object[] args) {
+ for (Object argument : args) {
+ if (argument == invalid) {
+ throw new IllegalArgumentException("argument type mismatch");
+ }
+ }
+ }
+
+ private void releaseArguments(final Object[] args, final boolean hasVarArgs) {
+ if (hasVarArgs && ((args.length > 0) && (args[args.length - 1] instanceof Object[]))) {
+ Object[] varArgs = (Object[]) args[args.length - 1];
+ for (Object object : varArgs) {
+ if (object instanceof V8Value) {
+ ((V8Value) object).close();
+ }
+ }
+ }
+ for (Object arg : args) {
+ if (arg instanceof V8Value) {
+ ((V8Value) arg).close();
+ }
+ }
+ }
+
+ private Object[] getArgs(final V8Object receiver, final MethodDescriptor methodDescriptor, final V8Array parameters, final boolean hasVarArgs) {
+ int numberOfParameters = methodDescriptor.method.getParameterTypes().length;
+ int varArgIndex = hasVarArgs ? numberOfParameters - 1 : numberOfParameters;
+ Object[] args = setDefaultValues(new Object[numberOfParameters], methodDescriptor.method.getParameterTypes(), receiver, methodDescriptor.includeReceiver);
+ List varArgs = new ArrayList();
+ populateParamters(parameters, varArgIndex, args, varArgs, methodDescriptor.includeReceiver);
+ if (hasVarArgs) {
+ Object varArgContainer = getVarArgContainer(methodDescriptor.method.getParameterTypes(), varArgs.size());
+ System.arraycopy(varArgs.toArray(), 0, varArgContainer, 0, varArgs.size());
+ args[varArgIndex] = varArgContainer;
+ }
+ return args;
+ }
+
+ private Object getVarArgContainer(final Class>[] parameterTypes, final int size) {
+ Class> clazz = parameterTypes[parameterTypes.length - 1];
+ if (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+ Object result = java.lang.reflect.Array.newInstance(clazz, size);
+ return result;
+ }
+
+ private void populateParamters(final V8Array parameters, final int varArgIndex, final Object[] args, final List varArgs, final boolean includeReceiver) {
+ int start = 0;
+ if (includeReceiver) {
+ start = 1;
+ }
+ for (int i = start; i < (parameters.length() + start); i++) {
+ if (i >= varArgIndex) {
+ varArgs.add(getArrayItem(parameters, i - start));
+ } else {
+ args[i] = getArrayItem(parameters, i - start);
+ }
+ }
+ }
+
+ private Object[] setDefaultValues(final Object[] parameters, final Class>[] parameterTypes, final V8Object receiver, final boolean includeReceiver) {
+ int start = 0;
+ if (includeReceiver) {
+ start = 1;
+ parameters[0] = receiver;
+ }
+ for (int i = start; i < parameters.length; i++) {
+ parameters[i] = getDefaultValue(parameterTypes[i]);
+ }
+ return parameters;
+ }
+
+ private Object getArrayItem(final V8Array array, final int index) {
+ try {
+ int type = array.getType(index);
+ switch (type) {
+ case INTEGER:
+ return array.getInteger(index);
+ case DOUBLE:
+ return array.getDouble(index);
+ case BOOLEAN:
+ return array.getBoolean(index);
+ case STRING:
+ return array.getString(index);
+ case V8_ARRAY:
+ case V8_TYPED_ARRAY:
+ return array.getArray(index);
+ case V8_OBJECT:
+ return array.getObject(index);
+ case V8_FUNCTION:
+ return array.getObject(index);
+ case V8_ARRAY_BUFFER:
+ return array.get(index);
+ case UNDEFINED:
+ return V8.getUndefined();
+ }
+ } catch (V8ResultUndefined e) {
+ // do nothing
+ }
+ return null;
+ }
+
+// void createNodeRuntime(final String fileName) {
+// _startNodeJS(v8RuntimePtr, fileName);
+// }
+
+ boolean pumpMessageLoop() {
+ return _pumpMessageLoop(v8RuntimePtr);
+ }
+
+ boolean isRunning() {
+ return _isRunning(v8RuntimePtr);
+ }
+
+ protected long initNewV8Object(final long v8RuntimePtr) {
+ return _initNewV8Object(v8RuntimePtr);
+ }
+
+ public 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);
+ }
+
+ protected int executeIntegerScript(final long v8RuntimePtr, final String script, final String scriptName, final int lineNumber) {
+ return _executeIntegerScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ protected double executeDoubleScript(final long v8RuntimePtr, final String script, final String scriptName, final int lineNumber) {
+ return _executeDoubleScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ protected String executeStringScript(final long v8RuntimePtr, final String script, final String scriptName, final int lineNumber) {
+ return _executeStringScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ protected boolean executeBooleanScript(final long v8RuntimePtr, final String script, final String scriptName, final int lineNumber) {
+ return _executeBooleanScript(v8RuntimePtr, script, scriptName, lineNumber);
+ }
+
+ protected Object executeScript(final long v8RuntimePtr, final int expectedType, final String script, final String scriptName, final int lineNumber) {
+ return _executeScript(v8RuntimePtr, expectedType, script, scriptName, lineNumber);
+ }
+
+ protected void executeVoidScript(final long v8RuntimePtr, final String script, final String scriptName, final int lineNumber) {
+ _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);
+ }
+
+ protected boolean contains(final long v8RuntimePtr, final long objectHandle, final String key) {
+ return _contains(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected String[] getKeys(final long v8RuntimePtr, final long objectHandle) {
+ return _getKeys(v8RuntimePtr, objectHandle);
+ }
+
+ protected int getInteger(final long v8RuntimePtr, final long objectHandle, final String key) {
+ return _getInteger(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected boolean getBoolean(final long v8RuntimePtr, final long objectHandle, final String key) {
+ return _getBoolean(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected double getDouble(final long v8RuntimePtr, final long objectHandle, final String key) {
+ return _getDouble(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected String getString(final long v8RuntimePtr, final long objectHandle, final String key) {
+ return _getString(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected Object get(final long v8RuntimePtr, final int expectedType, final long objectHandle, final String key) {
+ return _get(v8RuntimePtr, expectedType, objectHandle, key);
+ }
+
+ protected int executeIntegerFunction(final long v8RuntimePtr, final long objectHandle, final String name, final long parametersHandle) {
+ return _executeIntegerFunction(v8RuntimePtr, objectHandle, name, parametersHandle);
+ }
+
+ protected double executeDoubleFunction(final long v8RuntimePtr, final long objectHandle, final String name, final long parametersHandle) {
+ return _executeDoubleFunction(v8RuntimePtr, objectHandle, name, parametersHandle);
+ }
+
+ protected String executeStringFunction(final long v8RuntimePtr, final long handle, final String name, final long parametersHandle) {
+ return _executeStringFunction(v8RuntimePtr, handle, name, parametersHandle);
+ }
+
+ protected boolean executeBooleanFunction(final long v8RuntimePtr, final long handle, final String name, final long parametersHandle) {
+ return _executeBooleanFunction(v8RuntimePtr, handle, name, parametersHandle);
+ }
+
+ protected Object executeFunction(final long v8RuntimePtr, final int expectedType, final long objectHandle, final String name, final long parametersHandle) {
+ return _executeFunction(v8RuntimePtr, expectedType, objectHandle, name, parametersHandle);
+ }
+
+ protected Object executeFunction(final long v8RuntimePtr, final long receiverHandle, final long functionHandle, final long parametersHandle) {
+ return _executeFunction(v8RuntimePtr, receiverHandle, functionHandle, parametersHandle);
+ }
+
+ protected void executeVoidFunction(final long v8RuntimePtr, final long objectHandle, final String name, final long parametersHandle) {
+ _executeVoidFunction(v8RuntimePtr, objectHandle, name, parametersHandle);
+ }
+
+ protected boolean equals(final long v8RuntimePtr, final long objectHandle, final long that) {
+ return _equals(v8RuntimePtr, objectHandle, that);
+ }
+
+ protected String toString(final long v8RuntimePtr, final long objectHandle) {
+ return _toString(v8RuntimePtr, objectHandle);
+ }
+
+ protected boolean strictEquals(final long v8RuntimePtr, final long objectHandle, final long that) {
+ return _strictEquals(v8RuntimePtr, objectHandle, that);
+ }
+
+ protected boolean sameValue(final long v8RuntimePtr, final long objectHandle, final long that) {
+ return _sameValue(v8RuntimePtr, objectHandle, that);
+ }
+
+ protected int identityHash(final long v8RuntimePtr, final long objectHandle) {
+ return _identityHash(v8RuntimePtr, objectHandle);
+ }
+
+ protected void add(final long v8RuntimePtr, final long objectHandle, final String key, final int value) {
+ _add(v8RuntimePtr, objectHandle, key, value);
+ }
+
+ protected void addObject(final long v8RuntimePtr, final long objectHandle, final String key, final long value) {
+ _addObject(v8RuntimePtr, objectHandle, key, value);
+ }
+
+ protected void add(final long v8RuntimePtr, final long objectHandle, final String key, final boolean value) {
+ _add(v8RuntimePtr, objectHandle, key, value);
+ }
+
+ protected void add(final long v8RuntimePtr, final long objectHandle, final String key, final double value) {
+ _add(v8RuntimePtr, objectHandle, key, value);
+ }
+
+ protected void add(final long v8RuntimePtr, final long objectHandle, final String key, final String value) {
+ _add(v8RuntimePtr, objectHandle, key, value);
+ }
+
+ protected void addUndefined(final long v8RuntimePtr, final long objectHandle, final String key) {
+ _addUndefined(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected void addNull(final long v8RuntimePtr, final long objectHandle, final String key) {
+ _addNull(v8RuntimePtr, objectHandle, key);
+ }
+
+ protected long registerJavaMethod(final long v8RuntimePtr, final long objectHandle, final String functionName, final boolean voidMethod) {
+ return _registerJavaMethod(v8RuntimePtr, objectHandle, functionName, voidMethod);
+ }
+
+ protected long initNewV8ArrayBuffer(final long v8RuntimePtr, final ByteBuffer buffer, final int capacity) {
+ return _initNewV8ArrayBuffer(v8RuntimePtr, buffer, capacity);
+ }
+
+ protected long initNewV8ArrayBuffer(final long v8RuntimePtr, final int capacity) {
+ return _initNewV8ArrayBuffer(v8RuntimePtr, capacity);
+ }
+
+ public long initNewV8Int32Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8Int32Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8Float32Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8Float32Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8Float64Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8Float64Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8UInt32Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8UInt32Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8UInt16Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8UInt16Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8Int16Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8Int16Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8UInt8Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8UInt8Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8Int8Array(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8Int8Array(runtimePtr, bufferHandle, offset, size);
+ }
+
+ public long initNewV8UInt8ClampedArray(final long runtimePtr, final long bufferHandle, final int offset, final int size) {
+ return _initNewV8UInt8ClampedArray(runtimePtr, bufferHandle, offset, size);
+ }
+
+
+ protected ByteBuffer createV8ArrayBufferBackingStore(final long v8RuntimePtr, final long objectHandle, final int capacity) {
+ return _createV8ArrayBufferBackingStore(v8RuntimePtr, objectHandle, capacity);
+ }
+
+ protected long initNewV8Array(final long v8RuntimePtr) {
+ return _initNewV8Array(v8RuntimePtr);
+ }
+
+ protected long[] initNewV8Function(final long v8RuntimePtr) {
+ checkThread();
+ return _initNewV8Function(v8RuntimePtr);
+ }
+
+ protected int arrayGetSize(final long v8RuntimePtr, final long arrayHandle) {
+ return _arrayGetSize(v8RuntimePtr, arrayHandle);
+ }
+
+ protected int arrayGetInteger(final long v8RuntimePtr, final long arrayHandle, final int index) {
+ return _arrayGetInteger(v8RuntimePtr, arrayHandle, index);
+ }
+
+ protected boolean arrayGetBoolean(final long v8RuntimePtr, final long arrayHandle, final int index) {
+ return _arrayGetBoolean(v8RuntimePtr, arrayHandle, index);
+ }
+
+ protected byte arrayGetByte(final long v8RuntimePtr, final long arrayHandle, final int index) {
+ return _arrayGetByte(v8RuntimePtr, arrayHandle, index);
+ }
+
+ protected double arrayGetDouble(final long v8RuntimePtr, final long arrayHandle, final int index) {
+ return _arrayGetDouble(v8RuntimePtr, arrayHandle, index);
+ }
+
+ protected String arrayGetString(final long v8RuntimePtr, final long arrayHandle, final int index) {
+ return _arrayGetString(v8RuntimePtr, arrayHandle, index);
+ }
+
+ protected Object arrayGet(final long v8RuntimePtr, final int expectedType, final long arrayHandle, final int index) {
+ return _arrayGet(v8RuntimePtr, expectedType, arrayHandle, index);
+ }
+
+ protected void addArrayIntItem(final long v8RuntimePtr, final long arrayHandle, final int value) {
+ _addArrayIntItem(v8RuntimePtr, arrayHandle, value);
+ }
+
+ protected void addArrayBooleanItem(final long v8RuntimePtr, final long arrayHandle, final boolean value) {
+ _addArrayBooleanItem(v8RuntimePtr, arrayHandle, value);
+ }
+
+ protected void addArrayDoubleItem(final long v8RuntimePtr, final long arrayHandle, final double value) {
+ _addArrayDoubleItem(v8RuntimePtr, arrayHandle, value);
+ }
+
+ protected void addArrayStringItem(final long v8RuntimePtr, final long arrayHandle, final String value) {
+ _addArrayStringItem(v8RuntimePtr, arrayHandle, value);
+ }
+
+ protected void addArrayObjectItem(final long v8RuntimePtr, final long arrayHandle, final long value) {
+ _addArrayObjectItem(v8RuntimePtr, arrayHandle, value);
+ }
+
+ protected void addArrayUndefinedItem(final long v8RuntimePtr, final long arrayHandle) {
+ _addArrayUndefinedItem(v8RuntimePtr, arrayHandle);
+ }
+
+ protected void addArrayNullItem(final long v8RuntimePtr, final long arrayHandle) {
+ _addArrayNullItem(v8RuntimePtr, arrayHandle);
+ }
+
+ protected String getConstructorName(final long v8RuntimePtr, final long objectHandle) {
+ return _getConstructorName(v8RuntimePtr, objectHandle);
+ }
+
+ 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);
+ }
+
+ protected int getType(final long v8RuntimePtr, final long objectHandle, final int index) {
+ return _getType(v8RuntimePtr, objectHandle, index);
+ }
+
+ protected int getArrayType(final long v8RuntimePtr, final long objectHandle) {
+ return _getArrayType(v8RuntimePtr, objectHandle);
+ }
+
+ protected int getType(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _getType(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected void setPrototype(final long v8RuntimePtr, final long objectHandle, final long prototypeHandle) {
+ _setPrototype(v8RuntimePtr, objectHandle, prototypeHandle);
+ }
+
+ protected int[] arrayGetIntegers(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _arrayGetIntegers(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected double[] arrayGetDoubles(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _arrayGetDoubles(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected boolean[] arrayGetBooleans(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _arrayGetBooleans(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected byte[] arrayGetBytes(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _arrayGetBytes(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected String[] arrayGetStrings(final long v8RuntimePtr, final long objectHandle, final int index, final int length) {
+ return _arrayGetStrings(v8RuntimePtr, objectHandle, index, length);
+ }
+
+ protected int arrayGetIntegers(final long v8RuntimePtr, final long objectHandle, final int index, final int length, final int[] resultArray) {
+ return _arrayGetIntegers(v8RuntimePtr, objectHandle, index, length, resultArray);
+ }
+
+ protected int arrayGetDoubles(final long v8RuntimePtr, final long objectHandle, final int index, final int length, final double[] resultArray) {
+ return _arrayGetDoubles(v8RuntimePtr, objectHandle, index, length, resultArray);
+ }
+
+ protected int arrayGetBooleans(final long v8RuntimePtr, final long objectHandle, final int index, final int length, final boolean[] resultArray) {
+ return _arrayGetBooleans(v8RuntimePtr, objectHandle, index, length, resultArray);
+ }
+
+ protected int arrayGetBytes(final long v8RuntimePtr, final long objectHandle, final int index, final int length, final byte[] resultArray) {
+ return _arrayGetBytes(v8RuntimePtr, objectHandle, index, length, resultArray);
+ }
+
+ protected int arrayGetStrings(final long v8RuntimePtr, final long objectHandle, final int index, final int length, final String[] resultArray) {
+ return _arrayGetStrings(v8RuntimePtr, objectHandle, index, length, resultArray);
+ }
+
+ protected void terminateExecution(final long v8RuntimePtr) {
+ _terminateExecution(v8RuntimePtr);
+ }
+
+ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long methodDescriptor) {
+ _releaseMethodDescriptor(v8RuntimePtr, methodDescriptor);
+ }
+
+ 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);
+
+ private native long _createIsolate(String globalAlias);
+
+ // private native long _createInspector(long v8RuntimePtr, final V8InspectorDelegate inspectorDelegate, final String contextName);
+
+ // private native void _dispatchProtocolMessage(final long v8RuntimePtr, long v8InspectorPtr, final String protocolMessage);
+
+ // private native void _schedulePauseOnNextStatement(final long v8RuntimePtr, long v8InspectorPtr, final String reason);
+
+ private native int _executeIntegerScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber);
+
+ private native double _executeDoubleScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber);
+
+ private native String _executeStringScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber);
+
+ private native boolean _executeBooleanScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber);
+
+ private native Object _executeScript(long v8RuntimePtr, int expectedType, String script, String scriptName, int lineNumber);
+
+ private native void _executeVoidScript(long v8RuntimePtr, String script, String scriptName, int lineNumber);
+
+ private native void _release(long v8RuntimePtr, long objectHandle);
+
+ private native void _releaseMethodDescriptor(long v8RuntimePtr, long methodDescriptor);
+
+ private native boolean _contains(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native String[] _getKeys(long v8RuntimePtr, long objectHandle);
+
+ private native int _getInteger(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native boolean _getBoolean(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native double _getDouble(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native String _getString(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native Object _get(long v8RuntimePtr, int expectedType, long objectHandle, final String key);
+
+ private native int _executeIntegerFunction(long v8RuntimePtr, long objectHandle, String name, long parametersHandle);
+
+ private native double _executeDoubleFunction(long v8RuntimePtr, long objectHandle, String name, long parametersHandle);
+
+ private native String _executeStringFunction(long v8RuntimePtr2, long handle, String name, long parametersHandle);
+
+ private native boolean _executeBooleanFunction(long v8RuntimePtr2, long handle, String name, long parametersHandle);
+
+ private native Object _executeFunction(long v8RuntimePtr, int expectedType, long objectHandle, String name, long parametersHandle);
+
+ private native Object _executeFunction(long v8RuntimePtr, long receiverHandle, long functionHandle, long parametersHandle);
+
+ private native void _executeVoidFunction(long v8RuntimePtr, long objectHandle, final String name, final long parametersHandle);
+
+ private native boolean _equals(long v8RuntimePtr, long objectHandle, long that);
+
+ private native String _toString(long v8RuntimePtr, long ObjectHandle);
+
+ private native boolean _strictEquals(long v8RuntimePtr, long objectHandle, long that);
+
+ private native boolean _sameValue(long v8RuntimePtr, long objectHandle, long that);
+
+ private native int _identityHash(long v8RuntimePtr, long objectHandle);
+
+ private native void _add(long v8RuntimePtr, long objectHandle, final String key, final int value);
+
+ private native void _addObject(long v8RuntimePtr, long objectHandle, final String key, final long value);
+
+ private native void _add(long v8RuntimePtr, long objectHandle, final String key, final boolean value);
+
+ private native void _add(long v8RuntimePtr, long objectHandle, final String key, final double value);
+
+ private native void _add(long v8RuntimePtr, long objectHandle, final String key, final String value);
+
+ private native void _addUndefined(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native void _addNull(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native long _registerJavaMethod(long v8RuntimePtr, long objectHandle, final String functionName, final boolean voidMethod);
+
+ private native long _initNewV8Array(long v8RuntimePtr);
+
+ private native long[] _initNewV8Function(long v8RuntimePtr);
+
+ private native int _arrayGetSize(long v8RuntimePtr, long arrayHandle);
+
+ private native int _arrayGetInteger(long v8RuntimePtr, long arrayHandle, int index);
+
+ private native boolean _arrayGetBoolean(long v8RuntimePtr, long arrayHandle, int index);
+
+ private native byte _arrayGetByte(long v8RuntimePtr, long arrayHandle, int index);
+
+ private native double _arrayGetDouble(long v8RuntimePtr, long arrayHandle, int index);
+
+ private native String _arrayGetString(long v8RuntimePtr, long arrayHandle, int index);
+
+ private native Object _arrayGet(long v8RuntimePtr, int expectedType, long arrayHandle, int index);
+
+ private native void _addArrayIntItem(long v8RuntimePtr, long arrayHandle, int value);
+
+ private native void _addArrayBooleanItem(long v8RuntimePtr, long arrayHandle, boolean value);
+
+ private native void _addArrayDoubleItem(long v8RuntimePtr, long arrayHandle, double value);
+
+ private native void _addArrayStringItem(long v8RuntimePtr, long arrayHandle, String value);
+
+ private native void _addArrayObjectItem(long v8RuntimePtr, long arrayHandle, long value);
+
+ private native void _addArrayUndefinedItem(long v8RuntimePtr, long arrayHandle);
+
+ private native void _addArrayNullItem(long v8RuntimePtr, long arrayHandle);
+
+ private native int _getType(long v8RuntimePtr, long objectHandle, final String key);
+
+ private native int _getType(long v8RuntimePtr, long objectHandle, final int index);
+
+ private native int _getArrayType(long v8RuntimePtr, long objectHandle);
+
+ private native void _setPrototype(long v8RuntimePtr, long objectHandle, long prototypeHandle);
+
+ private native String _getConstructorName(long v8RuntimePtr, long objectHandle);
+
+ 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);
+
+ private native int[] _arrayGetIntegers(final long v8RuntimePtr, final long objectHandle, final int index, final int length);
+
+ private native boolean[] _arrayGetBooleans(final long v8RuntimePtr, final long objectHandle, final int index, final int length);
+
+ private native byte[] _arrayGetBytes(final long v8RuntimePtr, final long objectHandle, final int index, final int length);
+
+ private native String[] _arrayGetStrings(final long v8RuntimePtr, final long objectHandle, final int index, final int length);
+
+ private native int _arrayGetIntegers(final long v8RuntimePtr, final long objectHandle, final int index, final int length, int[] resultArray);
+
+ private native int _arrayGetDoubles(final long v8RuntimePtr, final long objectHandle, final int index, final int length, double[] resultArray);
+
+ private native int _arrayGetBooleans(final long v8RuntimePtr, final long objectHandle, final int index, final int length, boolean[] resultArray);
+
+ private native int _arrayGetBytes(final long v8RuntimePtr, final long objectHandle, final int index, final int length, byte[] resultArray);
+
+ private native int _arrayGetStrings(final long v8RuntimePtr, final long objectHandle, final int index, final int length, String[] resultArray);
+
+ private native long _initNewV8ArrayBuffer(long v8RuntimePtr, int capacity);
+
+ private native long _initNewV8ArrayBuffer(long v8RuntimePtr, ByteBuffer buffer, int capacity);
+
+ private native long _initNewV8Int32Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8UInt32Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8Float32Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8Float64Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8Int16Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8UInt16Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8Int8Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ private native long _initNewV8UInt8Array(long runtimePtr, long bufferHandle, int offset, int size);
+
+ 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();
+
+ private static native void _setFlags(String v8flags);
+
+ private native void _terminateExecution(final long v8RuntimePtr);
+
+ private native long _getGlobalObject(final long v8RuntimePtr);
+
+ private native static long _getBuildID();
+
+ // private native static void _startNodeJS(final long v8RuntimePtr, final String fileName);
+
+ private native static boolean _pumpMessageLoop(final long v8RuntimePtr);
+
+ 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()) {
+ notifyReferenceCreated(reference);
+ }
+ }
+
+ void releaseObjRef(final V8Value reference) {
+ if (!referenceHandlers.isEmpty()) {
+ notifyReferenceDisposed(reference);
+ }
+ objectReferences--;
+ }
+
+ public static void main(String[] args) {
+ V8 v8 = V8.createV8Runtime();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Array.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Array.java
new file mode 100644
index 000000000..9f3be54b8
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Array.java
@@ -0,0 +1,1189 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * A V8Value that represents a JavaScript array.
+ * JavaScript Arrays contain elements by index, but
+ * can also contain elements by 'key' which is why V8Array
+ * extends V8Object.
+ */
+public class V8Array extends V8Object {
+
+ protected V8Array() {
+
+ }
+
+ /**
+ * Creates a new V8Array and associates it with the given runtime.
+ * V8Arrays have native resources and as such, must be released.
+ *
+ * @param v8 The runtime on which to associate the V8Array.
+ */
+ public V8Array(final V8 v8) {
+ super(v8);
+ v8.checkThread();
+ }
+
+ protected V8Array(final V8 v8, final Object data) {
+ super(v8, data);
+ }
+
+ @Override
+ protected V8Value createTwin() {
+ return new V8Array(v8);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#twin()
+ */
+ @Override
+ public V8Array twin() {
+ 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);
+ released = false;
+ addObjectReference(handle);
+ }
+
+ /**
+ * Returns the length of this array.
+ *
+ * @return The length of the array.
+ */
+ public int length() {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetSize(v8.getV8RuntimePtr(), getHandle());
+ }
+
+ /**
+ * Returns the type of element at this given index.
+ *
+ * @param index The index at which to lookup the type of.
+ *
+ * @return The type of the element at the index.
+ */
+ public int getType(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.getType(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Gets the type of the array. Returns a 'type' if all the elements in the array
+ * have the same type, otherwise UNDEFINED is returned.
+ *
+ * @return The type of all the elements of the array, or UNDEFINED if they
+ * are not all the same type.
+ */
+ public int getType() {
+ v8.checkThread();
+ checkReleased();
+ return v8.getArrayType(v8.getV8RuntimePtr(), getHandle());
+ }
+
+ /**
+ * Gets the type of a subset of the array. The subset is specified by a start index
+ * and a length. UNDEFINED is returned if all the elements in the subset are not
+ * of the same type.
+ *
+ * @param index The start index.
+ * @param length The length.
+ *
+ * @return The type of the subset of the array or UNDEFINED if the subset is not
+ * all the same type.
+ */
+ public int getType(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.getType(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Returns the integer value associated at this index. If the value
+ * at this index does not exist, or if it's not an integer, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The integer value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not an integer.
+ */
+ public int getInteger(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetInteger(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Returns the boolean value associated at this index. If the value
+ * at this index does not exist, or if it's not a boolean, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The boolean value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not a boolean.
+ */
+ public boolean getBoolean(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetBoolean(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Returns the byte value associated at this index. If the value at
+ * this index does not exist, or cannot be cast to a byte, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return
+ * @return The byte value at this index or V8ResultUndefined
+ * if the index does not exist or the value cannot be cast to a byte.
+ */
+ public byte getByte(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetByte(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Returns the double value associated at this index. If the value
+ * at this index does not exist, or if it's not a double, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The double value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not a double.
+ */
+ public double getDouble(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetDouble(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Returns the String value associated at this index. If the value
+ * at this index does not exist, or if it's not a String, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The String value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not a String.
+ */
+ public String getString(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetString(v8.getV8RuntimePtr(), getHandle(), index);
+ }
+
+ /**
+ * Returns the integers contained in a subset of a V8Array. If the subset
+ * contains elements other than integers, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ *
+ * @return The integers contained in the subset of the array, or V8ResultUndefined
+ * exception.
+ */
+ public int[] getIntegers(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetIntegers(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Gets the integers contained in a subset of a V8Array. If the subset
+ * contains elements other than integers, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown. Finally, if the resultArray
+ * is not large enough to hold the results then IndexOutOfBoundsException is thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ * @param resultArray The array to put the results in.
+ *
+ * @return The number of elements added to the array.
+ */
+ public int getIntegers(final int index, final int length, final int[] resultArray) {
+ v8.checkThread();
+ checkReleased();
+ if (length > resultArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ return v8.arrayGetIntegers(v8.getV8RuntimePtr(), getHandle(), index, length, resultArray);
+ }
+
+ /**
+ * Returns the doubles contained in a subset of a V8Array. If the subset
+ * contains elements other than doubles, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ *
+ * @return The doubles contained in the subset of the array, or V8ResultUndefined
+ * exception.
+ */
+ public double[] getDoubles(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetDoubles(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Gets the doubles contained in a subset of a V8Array. If the subset
+ * contains elements other than doubles, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown. Finally, if the resultArray
+ * is not large enough to hold the results then IndexOutOfBoundsException is thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ * @param resultArray The array to put the results in.
+ *
+ * @return The number of elements added to the array.
+ */
+ public int getDoubles(final int index, final int length, final double[] resultArray) {
+ v8.checkThread();
+ checkReleased();
+ if (length > resultArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ return v8.arrayGetDoubles(v8.getV8RuntimePtr(), getHandle(), index, length, resultArray);
+ }
+
+ /**
+ * Returns the booleans contained in a subset of a V8Array. If the subset
+ * contains elements other than booleans, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ *
+ * @return The booleans contained in the subset of the array, or V8ResultUndefined
+ * exception.
+ */
+ public boolean[] getBooleans(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetBooleans(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Returns the bytes contained in a subset of a V8Array. If the subset
+ * contains elements that cannot be cast to bytes, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ *
+ * @return The bytes contained in the subset of the array, or V8ResultUndefined
+ * exception.
+ */
+ public byte[] getBytes(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetBytes(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Gets the booleans contained in a subset of a V8Array. If the subset
+ * contains elements other than booleans, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown. Finally, if the resultArray
+ * is not large enough to hold the results then IndexOutOfBoundsException is thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ * @param resultArray The array to put the results in.
+ *
+ * @return The number of elements added to the array.
+ */
+ public int getBooleans(final int index, final int length, final boolean[] resultArray) {
+ v8.checkThread();
+ checkReleased();
+ if (length > resultArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ return v8.arrayGetBooleans(v8.getV8RuntimePtr(), getHandle(), index, length, resultArray);
+ }
+
+ /**
+ * Gets the bytes contained in a subset of a V8Array. If the subset
+ * contains elements that cannot be cast to bytes, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown. Finally, if the resultArray
+ * is not large enough to hold the results then IndexOutOfBoundsException is thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ * @param resultArray The array to put the results in.
+ *
+ * @return The number of elements added to the array.
+ */
+ public int getBytes(final int index, final int length, final byte[] resultArray) {
+ v8.checkThread();
+ checkReleased();
+ if (length > resultArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ return v8.arrayGetBytes(v8.getV8RuntimePtr(), getHandle(), index, length, resultArray);
+ }
+
+ /**
+ * Returns the Strings contained in a subset of a V8Array. If the subset
+ * contains elements other than Strings, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ *
+ * @return The Strings contained in the subset of the array, or V8ResultUndefined
+ * exception.
+ */
+ public String[] getStrings(final int index, final int length) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGetStrings(v8.getV8RuntimePtr(), getHandle(), index, length);
+ }
+
+ /**
+ * Gets the Strings contained in a subset of a V8Array. If the subset
+ * contains elements other than Strings, then a V8ResultUndefined exception
+ * is thrown. Furthermore, if the subset is not entirely contained within the array,
+ * then V8ResultUndefined exception is also thrown. Finally, if the resultArray
+ * is not large enough to hold the results then IndexOutOfBoundsException is thrown.
+ *
+ * @param index The starting index.
+ * @param length The length.
+ * @param resultArray The array to put the results in.
+ *
+ * @return The number of elements added to the array.
+ */
+ public int getStrings(final int index, final int length, final String[] resultArray) {
+ v8.checkThread();
+ checkReleased();
+ if (length > resultArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ return v8.arrayGetStrings(v8.getV8RuntimePtr(), getHandle(), index, length, resultArray);
+ }
+
+ /**
+ * Gets the value at a given index as a Java Object. Primitives are boxed.
+ *
+ * @param index The index to get the value at.
+ *
+ * @return The value at the given index.
+ */
+ public Object get(final int index) {
+ v8.checkThread();
+ checkReleased();
+ return v8.arrayGet(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, index);
+ }
+
+ /**
+ * Returns the V8Array value associated at this index. If the value
+ * at this index does not exist, or if it's not a V8Array, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The V8Array value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not a V8Array.
+ */
+ public V8Array getArray(final int index) {
+ v8.checkThread();
+ checkReleased();
+ Object result = v8.arrayGet(v8.getV8RuntimePtr(), V8_ARRAY, objectHandle, index);
+ if ((result == null) || (result instanceof V8Array)) {
+ return (V8Array) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Returns the V8Object value associated at this index. If the value
+ * at this index does not exist, or if it's not a V8Object, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param index The index whose value to return.
+ *
+ * @return The V8Object value at this index or V8ResultUndefined
+ * if the index does not exist or the value is not a V8Object.
+ */
+ public V8Object getObject(final int index) {
+ v8.checkThread();
+ checkReleased();
+ Object result = v8.arrayGet(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, index);
+ if ((result == null) || (result instanceof V8Object)) {
+ return (V8Object) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Pushes an integer value 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 int value) {
+ v8.checkThread();
+ checkReleased();
+ v8.addArrayIntItem(v8.getV8RuntimePtr(), getHandle(), value);
+ return this;
+ }
+
+ /**
+ * Pushes a boolean value 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 boolean value) {
+ v8.checkThread();
+ checkReleased();
+ v8.addArrayBooleanItem(v8.getV8RuntimePtr(), getHandle(), value);
+ return this;
+ }
+
+ /**
+ * Pushes a double value 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 double value) {
+ v8.checkThread();
+ checkReleased();
+ v8.addArrayDoubleItem(v8.getV8RuntimePtr(), getHandle(), value);
+ return this;
+ }
+
+ /**
+ * Pushes a String value 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 String value) {
+ v8.checkThread();
+ checkReleased();
+ if (value == null) {
+ v8.addArrayNullItem(v8.getV8RuntimePtr(), getHandle());
+ } else if (value.equals(V8.getUndefined())) {
+ v8.addArrayUndefinedItem(v8.getV8RuntimePtr(), getHandle());
+ } else {
+ v8.addArrayStringItem(v8.getV8RuntimePtr(), getHandle(), value);
+ }
+ return this;
+ }
+
+ /**
+ * Pushes a V8Value 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 V8Value value) {
+ v8.checkThread();
+ checkReleased();
+ v8.checkRuntime(value);
+ if (value == null) {
+ v8.addArrayNullItem(v8.getV8RuntimePtr(), getHandle());
+ } else if (value.equals(V8.getUndefined())) {
+ v8.addArrayUndefinedItem(v8.getV8RuntimePtr(), getHandle());
+ } else {
+ v8.addArrayObjectItem(v8.getV8RuntimePtr(), getHandle(), value.getHandle());
+ }
+ 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;
+ *
+ * @return The receiver.
+ */
+ public V8Array pushNull() {
+ v8.checkThread();
+ checkReleased();
+ v8.addArrayNullItem(v8.getV8RuntimePtr(), getHandle());
+ return this;
+ }
+
+ /**
+ * Pushes undefined to the next available spot in the Array. In
+ * particular, this[length] = undefined;
+ *
+ * @return The receiver.
+ */
+ public V8Array pushUndefined() {
+ v8.checkThread();
+ checkReleased();
+ v8.addArrayUndefinedItem(v8.getV8RuntimePtr(), getHandle());
+ return this;
+ }
+
+ public static class Undefined extends V8Array {
+
+ public Undefined() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#isUndefined()
+ */
+ @Override
+ public boolean isUndefined() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#isReleased()
+ */
+ @Override
+ public boolean isReleased() {
+ 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() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#twin()
+ */
+ @Override
+ public V8Array.Undefined twin() {
+ return (V8Array.Undefined) super.twin();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "undefined";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object that) {
+ if ((that instanceof V8Object) && ((V8Object) that).isUndefined()) {
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return 919;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#getRuntime()
+ */
+ @Override
+ public V8 getRuntime() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, boolean)
+ */
+ @Override
+ public V8Object add(final String key, final boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, double)
+ */
+ @Override
+ public V8Object add(final String key, final double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, int)
+ */
+ @Override
+ public V8Object add(final String key, final int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, java.lang.String)
+ */
+ @Override
+ public V8Object add(final String key, final String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, com.eclipsesource.v8.V8Value)
+ */
+ @Override
+ public V8Object add(final String key, final V8Value value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#addUndefined(java.lang.String)
+ */
+ @Override
+ public V8Object addUndefined(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#contains(java.lang.String)
+ */
+ @Override
+ public boolean contains(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeArrayFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public V8Array executeArrayFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeBooleanFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public boolean executeBooleanFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeDoubleFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public double executeDoubleFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeIntegerFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public int executeIntegerFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeObjectFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public V8Object executeObjectFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeStringFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public String executeStringFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeVoidFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public void executeVoidFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getArray(java.lang.String)
+ */
+ @Override
+ public V8Array getArray(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getBoolean(java.lang.String)
+ */
+ @Override
+ public boolean getBoolean(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getDouble(java.lang.String)
+ */
+ @Override
+ public double getDouble(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getInteger(java.lang.String)
+ */
+ @Override
+ public int getInteger(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getKeys()
+ */
+ @Override
+ public String[] getKeys() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getObject(java.lang.String)
+ */
+ @Override
+ public V8Object getObject(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getString(java.lang.String)
+ */
+ @Override
+ public String getString(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getType(java.lang.String)
+ */
+ @Override
+ public int getType(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(com.eclipsesource.v8.JavaCallback, java.lang.String)
+ */
+ @Override
+ public V8Object registerJavaMethod(final JavaCallback callback, final String jsFunctionName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(com.eclipsesource.v8.JavaVoidCallback, java.lang.String)
+ */
+ @Override
+ public V8Object registerJavaMethod(final JavaVoidCallback callback, final String jsFunctionName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(java.lang.Object, java.lang.String, java.lang.String, java.lang.Class[], boolean)
+ */
+ @Override
+ public V8Object registerJavaMethod(final Object object, final String methodName, final String jsFunctionName, final Class>[] parameterTypes, final boolean includeReceiver) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#setPrototype(com.eclipsesource.v8.V8Object)
+ */
+ @Override
+ public V8Object setPrototype(final V8Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#get(int)
+ */
+ @Override
+ public Object get(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getArray(int)
+ */
+ @Override
+ public V8Array getArray(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getBoolean(int)
+ */
+ @Override
+ public boolean getBoolean(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getBooleans(int, int)
+ */
+ @Override
+ public boolean[] getBooleans(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getBytes(int, int)
+ */
+ @Override
+ public byte[] getBytes(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getBytes(int, int)
+ */
+ @Override
+ public int getBytes(final int index, final int length, final byte[] resultArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getByte(int)
+ */
+ @Override
+ public byte getByte(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getBooleans(int, int, boolean[])
+ */
+ @Override
+ public int getBooleans(final int index, final int length, final boolean[] resultArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getDouble(int)
+ */
+ @Override
+ public double getDouble(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getDoubles(int, int)
+ */
+ @Override
+ public double[] getDoubles(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getDoubles(int, int, double[])
+ */
+ @Override
+ public int getDoubles(final int index, final int length, final double[] resultArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getInteger(int)
+ */
+ @Override
+ public int getInteger(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getIntegers(int, int)
+ */
+ @Override
+ public int[] getIntegers(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getIntegers(int, int, int[])
+ */
+ @Override
+ public int getIntegers(final int index, final int length, final int[] resultArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getObject(int)
+ */
+ @Override
+ public V8Object getObject(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getString(int)
+ */
+ @Override
+ public String getString(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getStrings(int, int)
+ */
+ @Override
+ public String[] getStrings(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getStrings(int, int, java.lang.String[])
+ */
+ @Override
+ public int getStrings(final int index, final int length, final String[] resultArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getType()
+ */
+ @Override
+ public int getType() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getType(int)
+ */
+ @Override
+ public int getType(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#getType(int, int)
+ */
+ @Override
+ public int getType(final int index, final int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#length()
+ */
+ @Override
+ public int length() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#push(boolean)
+ */
+ @Override
+ public V8Array push(final boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#push(double)
+ */
+ @Override
+ public V8Array push(final double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#push(int)
+ */
+ @Override
+ public V8Array push(final int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#push(java.lang.String)
+ */
+ @Override
+ public V8Array push(final String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#push(com.eclipsesource.v8.V8Value)
+ */
+ @Override
+ public V8Array push(final V8Value value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Array#pushUndefined()
+ */
+ @Override
+ public V8Array pushUndefined() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java
new file mode 100644
index 000000000..88d0ee38e
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * 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;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * V8ArrayBuffers represent ArrayBuffers from V8, but are backed by a
+ * java.nio.ByteBuffer. This means that any data stored in a TypedArray
+ * can be accessed by the java.nio.ByteBuffer. This significantly improves
+ * performance of data access from Java to JavaScript.
+ *
+ * V8ArrayBuffers can either be constructed in Java, or returned from
+ * JavaScript.
+ *
+ */
+public class V8ArrayBuffer extends V8Value {
+
+ public ByteBuffer byteBuffer;
+
+ /**
+ * Creates a new V8ArrayBuffer on a given V8Runtime with a
+ * given capacity.
+ *
+ * @param v8 The runtime on which to create the ArrayBuffer
+ * @param capacity The capacity of the buffer
+ */
+ public V8ArrayBuffer(final V8 v8, final int capacity) {
+ super(v8);
+ initialize(v8.getV8RuntimePtr(), capacity);
+ byteBuffer = v8.createV8ArrayBufferBackingStore(v8.getV8RuntimePtr(), objectHandle, capacity);
+ byteBuffer.order(ByteOrder.nativeOrder());
+ }
+
+ 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");
+ }
+ initialize(v8.getV8RuntimePtr(), byteBuffer);
+ this.byteBuffer = byteBuffer;
+ byteBuffer.order(ByteOrder.nativeOrder());
+ }
+
+ @Override
+ protected void initialize(final long runtimePtr, final Object data) {
+ v8.checkThread();
+ if (data instanceof ByteBuffer) {
+ ByteBuffer buffer = (ByteBuffer) data;
+ int capacity = buffer.limit();
+ objectHandle = v8.initNewV8ArrayBuffer(v8.getV8RuntimePtr(), buffer, capacity);
+ } else {
+ int capacity = (Integer) data;
+ objectHandle = v8.initNewV8ArrayBuffer(v8.getV8RuntimePtr(), capacity);
+ }
+ released = false;
+ addObjectReference(objectHandle);
+ }
+
+ @Override
+ protected V8Value createTwin() {
+ return new V8ArrayBuffer(v8, byteBuffer);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#twin()
+ */
+ @Override
+ public V8ArrayBuffer twin() {
+ v8.checkThread();
+ checkReleased();
+ return (V8ArrayBuffer) super.twin();
+ }
+
+ /**
+ * Returns the buffers limit
+ *
+ * @return the buffers limit
+ */
+ public int limit() {
+ v8.checkThread();
+ checkReleased();
+ return byteBuffer.limit();
+ }
+
+ /**
+ * Returns the buffers capacity
+ *
+ * @return the buffers capacity
+ */
+ 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();
+ checkReleased();
+ return byteBuffer.asDoubleBuffer().limit();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Function.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Function.java
new file mode 100644
index 000000000..918a38f93
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Function.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+/**
+ * A V8Value that represents a JavaScript function.
+ * JavaScript functions cannot be created in Java, but
+ * can be returned as the result of invoking a JS script
+ * or JS Function.
+ */
+public class V8Function extends V8Object {
+
+ /**
+ * Create a JavaScript function, that when invoked will call
+ * the javaCallback passed to the receiver.
+ *
+ * @param v8 The v8 runtime on which to create this function
+ * @param javaCallback The callback to invoke
+ */
+ public V8Function(final V8 v8, final JavaCallback javaCallback) {
+ super(v8, javaCallback);
+ }
+
+ public V8Function(final V8 v8) {
+ this(v8, null);
+ }
+
+ @Override
+ protected V8Value createTwin() {
+ 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) {
+ super.initialize(runtimePtr, null);
+ return;
+ }
+ JavaCallback javaCallback = (JavaCallback) data;
+ long[] pointers = v8.initNewV8Function(runtimePtr);
+ // position 0 is the object reference, position 1 is the function reference
+ v8.createAndRegisterMethodDescriptor(javaCallback, pointers[1]);
+ released = false;
+ addObjectReference(pointers[0]);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#twin()
+ */
+ @Override
+ public V8Function twin() {
+ return (V8Function) super.twin();
+ }
+
+ /**
+ * Invoke the JavaScript function on the current runtime.
+ *
+ * @param receiver The object on which to call the function on. The
+ * receiver will be mapped to 'this' in JavaScript. If receiver is null
+ * or undefined, then the V8 runtime will be used instead.
+ * @param parameters The parameters passed to the JS Function.
+ *
+ * @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();
+ return v8.executeFunction(v8.getV8RuntimePtr(), receiverHandle, objectHandle, parametersHandle);
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Locker.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Locker.java
new file mode 100644
index 000000000..2d839cd14
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Locker.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+/**
+ * Represents a lock for a V8Runtime that can be moved between
+ * threads. When instantiated, the lock is automatically assigned
+ * to the current thread. If another thread wishes to acquire the
+ * lock, it must first be released.
+ */
+public class V8Locker {
+
+ private Thread thread = null;
+ private boolean released = false;
+ private V8 runtime;
+
+ public 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 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: 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. 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;
+ }
+
+ /**
+ * Checks if the locker has access to the current thread.
+ * If the locker holds a different thread, than an Error
+ * 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: current thread is " + Thread.currentThread() + " while the locker has thread " + thread);
+ }
+ }
+
+ /**
+ * Check if the current thread holds this lock.
+ *
+ * @return Returns true if the current thread holds the lock,
+ * false otherwise.
+ */
+ public boolean hasLock() {
+ return thread == Thread.currentThread();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Object.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Object.java
new file mode 100644
index 000000000..c0bdf3737
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Object.java
@@ -0,0 +1,1005 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+import java.lang.reflect.Method;
+
+/**
+ * The concrete class for all V8 Objects. V8Objects are
+ * JavaScript objects accessible in java. Specialized
+ * subclasses exist for V8Arrays and V8Functions.
+ *
+ * V8Object are JavaScript object with key value pairs.
+ * Specific get methods exist to access values as primitives.
+ * General get methods also exist, which return Java Objects
+ * and can be casted to the correct subclass.
+ *
+ * V8Object have native resources and must be released
+ * when they are no longer need in Java.
+ */
+public class V8Object extends V8Value {
+
+ /**
+ * Create a new V8Object and associate it with a runtime.
+ * Once created, it must be released.
+ *
+ * @param v8 The runtime on which to associate the V8Object.
+ */
+ public V8Object(final V8 v8) {
+ this(v8, null);
+ }
+
+ protected V8Object(final V8 v8, final Object data) {
+ super(v8);
+ if (v8 != null) {
+ this.v8.checkThread();
+ initialize(this.v8.getV8RuntimePtr(), data);
+ }
+ }
+
+ protected V8Object() {
+
+ }
+
+ @Override
+ protected V8Value createTwin() {
+ return new V8Object(v8);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#twin()
+ */
+ @Override
+ public V8Object twin() {
+ return (V8Object) super.twin();
+ }
+
+ /**
+ * Determine if a key/value pair with this key exists in
+ * the Object.
+ *
+ * @param key The key to check
+ * @return True if the key exists, false otherwise.
+ */
+ public boolean contains(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.contains(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns all the keys associated with this JavaScript Object.
+ * Keys associated with the objects prototype are not returned.
+ *
+ * @return The keys associated with this JavaScript Object.
+ */
+ public String[] getKeys() {
+ v8.checkThread();
+ checkReleased();
+ return v8.getKeys(v8.getV8RuntimePtr(), objectHandle);
+ }
+
+ /**
+ * Returns the type of the value associated with this Key, or
+ * UNDEFINED if the key does not exist. Types are specified as
+ * integer constants. The types are all defined in V8Value.
+ *
+ * @param key The key whose type to lookup.
+ *
+ * @return The Type of the value associated with this key
+ */
+ public int getType(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.getType(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns the value associated with this key. Values are Java Objects.
+ * If the value is a primitive, its boxed type is returned. If the
+ * value is a V8Value, it must be released.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The value associated with this key.
+ */
+ public Object get(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.get(v8.getV8RuntimePtr(), V8_OBJECT, objectHandle, key);
+ }
+
+ /**
+ * Returns the integer value associated with this key. If the value
+ * associated with this key does not exist, or if it's not an integer, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The integer value associated with this key, or V8ResultUndefined
+ * if the key does not exist or the value is not an integer.
+ */
+ public int getInteger(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.getInteger(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns the boolean value associated with this key. If the value
+ * associated with this key does not exist, or if it's not a boolean, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The boolean value associated with this key, or V8ResultUndefined
+ * if the key does not exist or the value is not a boolean.
+ */
+ public boolean getBoolean(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.getBoolean(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns the double value associated with this key. If the value
+ * associated with this key does not exist, or if it's not a double, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The double value associated with this key, or V8ResultUndefined
+ * if the key does not exist or the value is not a double.
+ */
+ public double getDouble(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.getDouble(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns the String value associated with this key. If the value
+ * associated with this key does not exist, or if it's not a String, then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The String value associated with this key, or V8ResultUndefined
+ * if the key does not exist or the value is not a String.
+ */
+ public String getString(final String key) {
+ v8.checkThread();
+ checkReleased();
+ checkKey(key);
+ return v8.getString(v8.getV8RuntimePtr(), objectHandle, key);
+ }
+
+ /**
+ * Returns the V8Array value associated with this key. If the value
+ * associated with this key does not exist then UNDEFINED is returned.
+ * If the value exists but is not an array then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The V8Array value associated with this key.
+ */
+ 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;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Returns the V8Object value associated with this key. If the value
+ * associated with this key does not exist then UNDEFINED is returned.
+ * If the value exists but is not an JS Object then
+ * V8ResultUndefined exception is thrown.
+ *
+ * @param key The key whose value to return.
+ *
+ * @return The V8Object value associated with this key.
+ */
+ 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;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a integer. If the
+ * result is not an integer, or does not exist, then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return An integer representing the result of the function call or V8ResultUndefined
+ * if the result is not an integer.
+ */
+ 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);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a double. If the
+ * result is not a double, or does not exist, then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A double representing the result of the function call or V8ResultUndefined
+ * if the result is not a double.
+ */
+ 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);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a String. If the
+ * result is not a String, or does not exist, then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A String representing the result of the function call or V8ResultUndefined
+ * if the result is not a String.
+ */
+ 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);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a boolean. If the
+ * result is not a boolean, or does not exist, then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A boolean representing the result of the function call or V8ResultUndefined
+ * if the result is not a boolean.
+ */
+ 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);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a V8Array. If the
+ * result is not a V8Array then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A V8Array representing the result of the function call or V8ResultUndefined
+ * if the result is not a V8Array. The result must be released.
+ */
+ 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) {
+ return (V8Array) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a V8Object. If the
+ * result is not a V8Object then V8ResultUndefined is thrown.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A V8Object representing the result of the function call or V8ResultUndefined
+ * if the result is not a V8Object. The result must be released.
+ */
+ 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) {
+ return (V8Object) result;
+ }
+ throw new V8ResultUndefined();
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a Java Object.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ *
+ * @return A Java Object representing the result of the function call.
+ */
+ 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);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a Java Object.
+ *
+ * @param name The name of the JS Function to call
+ * @return The result of this JS Function
+ */
+ public Object executeJSFunction(final String name) {
+ return executeFunction(name, null);
+ }
+
+ /**
+ * Invoke a JavaScript function and return the result as a Java Object.
+ *
+ * @param name The name of the JS Function to call.
+ * @param parameters The parameters to pass to the function.
+ * @return A Java Object representing the result of the function call.
+ */
+ public Object executeJSFunction(final String name, final Object... parameters) {
+ if (parameters == null) {
+ return executeFunction(name, null);
+ }
+ V8Array parameterArray = new V8Array(v8.getRuntime());
+ try {
+ for (Object object : parameters) {
+ if (object == null) {
+ parameterArray.pushNull();
+ } else if (object instanceof V8Value) {
+ parameterArray.push((V8Value) object);
+ } else if (object instanceof Integer) {
+ parameterArray.push(object);
+ } else if (object instanceof Double) {
+ 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(object);
+ } else if (object instanceof String) {
+ parameterArray.push((String) object);
+ } else {
+ throw new IllegalArgumentException("Unsupported Object of type: " + object.getClass());
+ }
+ }
+ return executeFunction(name, parameterArray);
+ } finally {
+ parameterArray.close();
+ }
+ }
+
+ /**
+ * Invokes a JavaScript function which does not return a result.
+ *
+ * @param name The name of the JS Function to call.
+ *
+ * @param parameters The parameters to pass to the function. Parameters must be released.
+ */
+ 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);
+ }
+
+ /**
+ * Adds a key value pair to the receiver where the value is an integer.
+ *
+ * @param key The key to associate the value with.
+ * @param value The value to add.
+ *
+ * @return The receiver.
+ */
+ public V8Object add(final String key, final int value) {
+ v8.checkThread();
+ checkReleased();
+ v8.add(v8.getV8RuntimePtr(), objectHandle, key, value);
+ return this;
+ }
+
+ /**
+ * Adds a key value pair to the receiver where the value is a boolean.
+ *
+ * @param key The key to associate the value with.
+ * @param value The value to add.
+ *
+ * @return The receiver.
+ */
+ public V8Object add(final String key, final boolean value) {
+ v8.checkThread();
+ checkReleased();
+ v8.add(v8.getV8RuntimePtr(), objectHandle, key, value);
+ return this;
+ }
+
+ /**
+ * Adds a key value pair to the receiver where the value is a double.
+ *
+ * @param key The key to associate the value with.
+ * @param value The value to add.
+ *
+ * @return The receiver.
+ */
+ public V8Object add(final String key, final double value) {
+ v8.checkThread();
+ checkReleased();
+ v8.add(v8.getV8RuntimePtr(), objectHandle, key, value);
+ return this;
+ }
+
+ /**
+ * Adds a key value pair to the receiver where the value is a String.
+ *
+ * @param key The key to associate the value with.
+ * @param value The value to add.
+ *
+ * @return The receiver.
+ */
+ public V8Object add(final String key, final String value) {
+ v8.checkThread();
+ checkReleased();
+ if (value == null) {
+ v8.addNull(v8.getV8RuntimePtr(), objectHandle, key);
+ } else if (value.equals(V8.getUndefined())) {
+ v8.addUndefined(v8.getV8RuntimePtr(), objectHandle, key);
+ } else {
+ v8.add(v8.getV8RuntimePtr(), objectHandle, key, value);
+ }
+ return this;
+ }
+
+ /**
+ * Adds a key value pair to the receiver where the value is a V8Value.
+ *
+ * @param key The key to associate the value with.
+ * @param value The value to add.
+ *
+ * @return The receiver.
+ */
+ 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())) {
+ v8.addUndefined(v8.getV8RuntimePtr(), objectHandle, key);
+ } else {
+ v8.addObject(v8.getV8RuntimePtr(), objectHandle, key, value.getHandle());
+ }
+ return this;
+ }
+
+ /**
+ * Associate UNDEFINED with the given key.
+ *
+ * @param key The key to associate UNDEFINED with.
+ *
+ * @return The receiver.
+ */
+ public V8Object addUndefined(final String key) {
+ v8.checkThread();
+ checkReleased();
+ v8.addUndefined(v8.getV8RuntimePtr(), objectHandle, key);
+ return this;
+ }
+
+ /**
+ * Associate NULL with the given key.
+ *
+ * @param key The key to associate NULL with.
+ *
+ * @return The receiver.
+ */
+ public V8Object addNull(final String key) {
+ v8.checkThread();
+ checkReleased();
+ v8.addNull(v8.getV8RuntimePtr(), objectHandle, key);
+ return this;
+ }
+
+ /**
+ * Sets the prototype of the receiver.
+ *
+ * @param value The prototype to associate with this V8Object.
+ *
+ * @return The receiver.
+ */
+ public V8Object setPrototype(final V8Object value) {
+ v8.checkThread();
+ checkReleased();
+ v8.setPrototype(v8.getV8RuntimePtr(), objectHandle, value.getHandle());
+ return this;
+ }
+
+ /**
+ * Register a Java method as a JavaScript function. When the JS Function is invoked
+ * the Java method will be called.
+ *
+ * @param callback The JavaCallback to call when the JSFunction is invoked.
+ * @param jsFunctionName The name of the JSFunction.
+ *
+ * @return The receiver.
+ */
+ public V8Object registerJavaMethod(final JavaCallback callback, final String jsFunctionName) {
+ v8.checkThread();
+ checkReleased();
+ v8.registerCallback(callback, getHandle(), jsFunctionName);
+ return this;
+ }
+
+ /**
+ * Register a void Java method as a JavaScript function. When the JS Function is invoked
+ * the Java method will be called.
+ *
+ * @param callback The JavaVoidCallback to call when the JSFunction is invoked.
+ * @param jsFunctionName The name of the JSFunction.
+ *
+ * @return The receiver.
+ */
+ public V8Object registerJavaMethod(final JavaVoidCallback callback, final String jsFunctionName) {
+ v8.checkThread();
+ checkReleased();
+ v8.registerVoidCallback(callback, getHandle(), jsFunctionName);
+ return this;
+ }
+
+ /**
+ * Register a Java method reflectively given it's name a signature.
+ *
+ * @param object The Java Object on which the method is defined.
+ * @param methodName The name of the method to register.
+ * @param jsFunctionName The name of the JavaScript function to register the
+ * method with.
+ * @param parameterTypes The parameter types of the method.
+ *
+ * @return The receiver.
+ */
+ public V8Object registerJavaMethod(final Object object, final String methodName, final String jsFunctionName, final Class>[] parameterTypes) {
+ return registerJavaMethod(object, methodName, jsFunctionName, parameterTypes, false);
+ }
+
+ /**
+ * Register a Java method reflectively given it's name a signature. The option to include
+ * the JS Object in the callback can be specified by setting includeReceiver true.
+ *
+ * @param object The Java Object on which the method is defined.
+ * @param methodName The name of the method to register.
+ * @param jsFunctionName The name of the JavaScript function to register the
+ * method with.
+ * @param parameterTypes The parameter types of the method.
+ * @param includeReceiver True if the first parameter should include the JS Object,
+ * false otherwise.
+ *
+ * @return The receiver.
+ */
+ public V8Object registerJavaMethod(final Object object, final String methodName, final String jsFunctionName, final Class>[] parameterTypes, final boolean includeReceiver) {
+ v8.checkThread();
+ checkReleased();
+ try {
+ Method method = object.getClass().getMethod(methodName, parameterTypes);
+ method.setAccessible(true);
+ v8.registerCallback(object, method, getHandle(), jsFunctionName, includeReceiver);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ return this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ if (isReleased() || v8.isReleased()) {
+ return "[Object released]";
+ }
+ v8.checkThread();
+ return v8.toString(v8.getV8RuntimePtr(), getHandle());
+ }
+
+ private void checkKey(final String key) {
+ if (key == null) {
+ throw new IllegalArgumentException("Key cannot be null");
+ }
+ }
+
+ public static class Undefined extends V8Object {
+
+ public Undefined() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#isUndefined()
+ */
+ @Override
+ public boolean isUndefined() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#isReleased()
+ */
+ @Override
+ public boolean isReleased() {
+ 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() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#twin()
+ */
+ @Override
+ public Undefined twin() {
+ return (Undefined) super.twin();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "undefined";
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object that) {
+ if ((that instanceof V8Object) && ((V8Object) that).isUndefined()) {
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return 919;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, boolean)
+ */
+ @Override
+ public V8Object add(final String key, final boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Value#getRuntime()
+ */
+ @Override
+ public V8 getRuntime() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, double)
+ */
+ @Override
+ public V8Object add(final String key, final double value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, int)
+ */
+ @Override
+ public V8Object add(final String key, final int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeJSFunction(java.lang.String, java.lang.Object[])
+ */
+ @Override
+ public Object executeJSFunction(final String name, final Object... parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public Object executeFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, java.lang.String)
+ */
+ @Override
+ public V8Object add(final String key, final String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#add(java.lang.String, com.eclipsesource.v8.V8Value)
+ */
+ @Override
+ public V8Object add(final String key, final V8Value value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#addUndefined(java.lang.String)
+ */
+ @Override
+ public V8Object addUndefined(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#contains(java.lang.String)
+ */
+ @Override
+ public boolean contains(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeArrayFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public V8Array executeArrayFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeBooleanFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public boolean executeBooleanFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeDoubleFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public double executeDoubleFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeIntegerFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public int executeIntegerFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeObjectFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public V8Object executeObjectFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeStringFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public String executeStringFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#executeVoidFunction(java.lang.String, com.eclipsesource.v8.V8Array)
+ */
+ @Override
+ public void executeVoidFunction(final String name, final V8Array parameters) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getArray(java.lang.String)
+ */
+ @Override
+ public V8Array getArray(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getBoolean(java.lang.String)
+ */
+ @Override
+ public boolean getBoolean(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getDouble(java.lang.String)
+ */
+ @Override
+ public double getDouble(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getInteger(java.lang.String)
+ */
+ @Override
+ public int getInteger(final String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getKeys()
+ */
+ @Override
+ public String[] getKeys() {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getObject(java.lang.String)
+ */
+ @Override
+ public V8Object getObject(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getString(java.lang.String)
+ */
+ @Override
+ public String getString(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#getType(java.lang.String)
+ */
+ @Override
+ public int getType(final String key) throws V8ResultUndefined {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(com.eclipsesource.v8.JavaCallback, java.lang.String)
+ */
+ @Override
+ public V8Object registerJavaMethod(final JavaCallback callback, final String jsFunctionName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(com.eclipsesource.v8.JavaVoidCallback, java.lang.String)
+ */
+ @Override
+ public V8Object registerJavaMethod(final JavaVoidCallback callback, final String jsFunctionName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#registerJavaMethod(java.lang.Object, java.lang.String, java.lang.String, java.lang.Class[], boolean)
+ */
+ @Override
+ public V8Object registerJavaMethod(final Object object, final String methodName, final String jsFunctionName, final Class>[] parameterTypes, final boolean includeReceiver) {
+ throw new UnsupportedOperationException();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.eclipsesource.v8.V8Object#setPrototype(com.eclipsesource.v8.V8Object)
+ */
+ @Override
+ public V8Object setPrototype(final V8Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ResultUndefined.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ResultUndefined.java
new file mode 100644
index 000000000..4d15d6378
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ResultUndefined.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * An exception that's used to indicate that method that should have returned a
+ * primitive, returned an Undefined instead.
+ *
+ * In Java, Undefined cannot be returned for all methods, especially if
+ * the method returns a primitive (int, double, boolean) or a String.
+ * In this case, if an Undefined should be returned from JS, then an instance
+ * of this exception is thrown.
+ */
+@SuppressWarnings("serial")
+public class V8ResultUndefined extends V8RuntimeException {
+
+ V8ResultUndefined(final String message) {
+ super(message);
+ }
+
+ V8ResultUndefined() {
+ super();
+ }
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8RuntimeException.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8RuntimeException.java
new file mode 100644
index 000000000..2ea34af12
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8RuntimeException.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * A top-level exception used to indicate that a script failed. In most cases
+ * a more specific exception will be thrown.
+ */
+@SuppressWarnings("serial")
+public class V8RuntimeException extends RuntimeException {
+
+ V8RuntimeException() {
+ }
+
+ V8RuntimeException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptCompilationException.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptCompilationException.java
new file mode 100644
index 000000000..30fcf1447
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptCompilationException.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * An exception used to indicate that a script failed to compile.
+ */
+@SuppressWarnings("serial")
+public class V8ScriptCompilationException extends V8ScriptException {
+
+ public V8ScriptCompilationException(final String fileName, final int lineNumber,
+ final String message, final String sourceLine, final int startColumn, final int endColumn) {
+ super(fileName, lineNumber, message, sourceLine, startColumn, endColumn, null, null);
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptException.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptException.java
new file mode 100644
index 000000000..aa59be0bf
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptException.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * An exception that indicates that the execution of a script failed.
+ * Details about the exception, such as the line number, stack trace, and
+ * message can retrieved using the accessors.
+ */
+@SuppressWarnings("serial")
+public abstract class V8ScriptException extends V8RuntimeException {
+
+ private final String fileName;
+ private final int lineNumber;
+ private final String jsMessage;
+ private final String sourceLine;
+ private final int startColumn;
+ private final int endColumn;
+ private final String jsStackTrace;
+
+ V8ScriptException(final String fileName,
+ final int lineNumber,
+ final String jsMessage,
+ final String sourceLine,
+ final int startColumn,
+ final int endColumn,
+ final String jsStackTrace,
+ final Throwable cause) {
+ this.fileName = fileName;
+ this.lineNumber = lineNumber;
+ this.jsMessage = jsMessage;
+ this.sourceLine = sourceLine;
+ this.startColumn = startColumn;
+ this.endColumn = endColumn;
+ this.jsStackTrace = jsStackTrace;
+ if (cause != null) {
+ initCause(cause);
+ }
+ }
+
+ /**
+ * Get the JavaScript Stack as a String.
+ *
+ * @return The JavaScript stack.
+ */
+ public String getJSStackTrace() {
+ return jsStackTrace;
+ }
+
+ /**
+ * Get the file name contains the script that was currently executing.
+ *
+ * @return The file name that contains the script.
+ */
+ public String getFileName() {
+ return fileName;
+ }
+
+ /**
+ * Get the line number that the failure occurred on.
+ *
+ * @return The line number the failure occurred on.
+ */
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ /**
+ * Get the JavaScript column where the error begins.
+ *
+ * @return The JavaScript column where the error begins.
+ */
+ public int getStartColumn() {
+ return startColumn;
+ }
+
+ /**
+ * Get the JavaScript column where the error ends.
+ *
+ * @return The JavaScript column where the error ends.
+ */
+ public int getEndColumn() {
+ return endColumn;
+ }
+
+ /**
+ * Get the JavaScript line of source that caused the error.
+ *
+ * @return The JavaScript line of source that caused the error.
+ */
+ public String getSourceLine() {
+ return sourceLine;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append(createMessageLine());
+ result.append(createMessageDetails());
+ result.append(createJSStackDetails());
+ result.append("\n");
+ result.append(this.getClass().getName());
+ return result.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return createMessageLine();
+ }
+
+ /**
+ * Get the message set by the JavaScript exception.
+ *
+ * @return The message set by the JavaScript exception.
+ */
+ public String getJSMessage() {
+ return jsMessage;
+ }
+
+ private String createMessageLine() {
+ return fileName + ":" + lineNumber + ": " + jsMessage;
+ }
+
+ private String createJSStackDetails() {
+ if (jsStackTrace != null) {
+ return "\n" + jsStackTrace;
+ }
+ return "";
+ }
+
+ private String createMessageDetails() {
+ StringBuilder result = new StringBuilder();
+ if ((sourceLine != null) && !sourceLine.isEmpty()) {
+ result.append('\n');
+ result.append(sourceLine);
+ result.append('\n');
+ if (startColumn >= 0) {
+ result.append(createCharSequence(startColumn, ' '));
+ result.append(createCharSequence(endColumn - startColumn, '^'));
+ }
+ }
+ return result.toString();
+ }
+
+ private char[] createCharSequence(final int length, final char c) {
+ char[] result = new char[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = c;
+ }
+ return result;
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptExecutionException.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptExecutionException.java
new file mode 100644
index 000000000..e320f8a2d
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8ScriptExecutionException.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * An exception used to indicate that a script failed to execute.
+ */
+@SuppressWarnings("serial")
+public class V8ScriptExecutionException extends V8ScriptException {
+
+ V8ScriptExecutionException(final String fileName,
+ final int lineNumber,
+ final String message,
+ final String sourceLine,
+ final int startColumn,
+ final int endColumn,
+ final String jsStackTrace) {
+ this(fileName, lineNumber, message, sourceLine, startColumn, endColumn, jsStackTrace, null);
+ }
+
+ public V8ScriptExecutionException(final String fileName,
+ final int lineNumber,
+ final String message,
+ final String sourceLine,
+ final int startColumn,
+ final int endColumn,
+ final String jsStackTrace,
+ final Throwable cause) {
+ super(fileName, lineNumber, message, sourceLine, startColumn, endColumn, jsStackTrace, cause);
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8TypedArray.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8TypedArray.java
new file mode 100644
index 000000000..423f9a71a
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8TypedArray.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * A representation of a JS TypedArray in Java. The typed array is simply a 'view' onto
+ * a back buffer.
+ */
+public class V8TypedArray extends V8Array {
+
+ /**
+ * Create a new TypedArray from a specified ArrayBuffer, type, offset and size. For
+ * example, a V8Int32Array is a typed array where each value is a 32-bit integer. The
+ * typed array is backed by the V8ArrayBuffer.
+ *
+ * @param v8 The V8Runtime on which to create this Int32Array
+ * @param type The type of Array to create. Currently Integer and Byte are supported.
+ * @param buffer The buffer used to back the typed array
+ * @param offset The offset into the buffer at which to start the the array
+ * @param size The size of the typed array
+ */
+ public V8TypedArray(final V8 v8, final V8ArrayBuffer buffer, final int type, final int offset, final int size) {
+ super(v8, new V8ArrayData(buffer, offset, size, type));
+ }
+
+ private V8TypedArray(final V8 v8) {
+ 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.
+ *
+ * @return The V8ArrayBuffer used to back this TypedArray.
+ */
+ public V8ArrayBuffer getBuffer() {
+ return (V8ArrayBuffer) get("buffer");
+ }
+
+ @Override
+ protected void initialize(final long runtimePtr, final Object data) {
+ v8.checkThread();
+ if (data == null) {
+ super.initialize(runtimePtr, data);
+ return;
+ }
+ V8ArrayData arrayData = (V8ArrayData) data;
+ checkArrayProperties(arrayData);
+ long handle = createTypedArray(runtimePtr, arrayData);
+ released = false;
+ addObjectReference(handle);
+ }
+
+ private long createTypedArray(final long runtimePtr, final V8ArrayData arrayData) {
+ switch (arrayData.type) {
+ case V8Value.FLOAT_32_ARRAY:
+ return v8.initNewV8Float32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.FLOAT_64_ARRAY:
+ return v8.initNewV8Float64Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.UNSIGNED_INT_32_ARRAY:
+ return v8.initNewV8UInt32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.INT_16_ARRAY:
+ return v8.initNewV8Int16Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.UNSIGNED_INT_16_ARRAY:
+ return v8.initNewV8UInt16Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.INTEGER:
+ return v8.initNewV8Int32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.UNSIGNED_INT_8_ARRAY:
+ return v8.initNewV8UInt8Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ case V8Value.INT_8_ARRAY:
+ return v8.initNewV8Int8Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size);
+ 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.getStringRepresentation(arrayData.type));
+ }
+ }
+
+ /**
+ * Computes the size of the structures required for each TypedArray variation.
+ *
+ * @param type The type of the TypeArray
+ * @return The size of the structures required
+ */
+ public static int getStructureSize(final int type) {
+ switch (type) {
+ case V8Value.FLOAT_64_ARRAY:
+ return 8;
+ case V8Value.INT_32_ARRAY:
+ case V8Value.UNSIGNED_INT_32_ARRAY:
+ case V8Value.FLOAT_32_ARRAY:
+ return 4;
+ case V8Value.UNSIGNED_INT_16_ARRAY:
+ case V8Value.INT_16_ARRAY:
+ return 2;
+ case V8Value.INT_8_ARRAY:
+ case V8Value.UNSIGNED_INT_8_ARRAY:
+ case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY:
+ return 1;
+ default:
+ throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentation(type));
+ }
+ }
+
+ private void checkArrayProperties(final V8ArrayData arrayData) {
+ checkOffset(arrayData);
+ checkSize(arrayData);
+ }
+
+ private void checkSize(final V8ArrayData arrayData) {
+ if (arrayData.size < 0) {
+ throw new IllegalStateException("RangeError: Invalid typed array length");
+ }
+ int limit = (arrayData.size * getStructureSize(arrayData.type)) + arrayData.offset;
+ if (limit > arrayData.buffer.limit()) {
+ throw new IllegalStateException("RangeError: Invalid typed array length");
+ }
+ }
+
+ private void checkOffset(final V8ArrayData arrayData) {
+ if ((arrayData.offset % getStructureSize(arrayData.type)) != 0) {
+ throw new IllegalStateException("RangeError: Start offset of Int32Array must be a multiple of " + getStructureSize(arrayData.type));
+ }
+ }
+
+ private static class V8ArrayData {
+ private V8ArrayBuffer buffer;
+ private int offset;
+ private int size;
+ private int type;
+
+ public V8ArrayData(final V8ArrayBuffer buffer, final int offset, final int size, final int type) {
+ this.buffer = buffer;
+ this.offset = offset;
+ this.size = size;
+ this.type = type;
+ }
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java
new file mode 100644
index 000000000..533410b95
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+/**
+ * A base class for all V8 resources. V8 resources must
+ * be closed/released. The rules for releasing resources is as
+ * follows:
+ *
+ * 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 don’t need to worry about it,
+ * with one caveat; if the object was returned to you as a
+ * result of a method call, you must close it.
+ */
+abstract public class V8Value implements Releasable {
+
+ public static final int NULL = 0;
+ public static final int UNKNOWN = 0;
+ public static final int INTEGER = 1;
+ public static final int INT_32_ARRAY = 1;
+ public static final int DOUBLE = 2;
+ public static final int FLOAT_64_ARRAY = 2;
+ public static final int BOOLEAN = 3;
+ public static final int STRING = 4;
+ public static final int V8_ARRAY = 5;
+ public static final int V8_OBJECT = 6;
+ public static final int V8_FUNCTION = 7;
+ public static final int V8_TYPED_ARRAY = 8;
+ public static final int BYTE = 9;
+ public static final int INT_8_ARRAY = 9;
+ public static final int V8_ARRAY_BUFFER = 10;
+ public static final int UNSIGNED_INT_8_ARRAY = 11;
+ public static final int UNSIGNED_INT_8_CLAMPED_ARRAY = 12;
+ public static final int INT_16_ARRAY = 13;
+ public static final int UNSIGNED_INT_16_ARRAY = 14;
+ public static final int UNSIGNED_INT_32_ARRAY = 15;
+ public static final int FLOAT_32_ARRAY = 16;
+ public static final int UNDEFINED = 99;
+
+ protected V8 v8;
+ protected long objectHandle;
+ protected boolean released = true;
+
+ protected V8Value() {
+ super();
+ }
+
+ protected V8Value(final V8 v8) {
+ if (v8 == null) {
+ this.v8 = (V8) this;
+ } else {
+ this.v8 = v8;
+ }
+ }
+
+ protected void initialize(final long runtimePtr, final Object data) {
+ long objectHandle = v8.initNewV8Object(runtimePtr);
+ released = false;
+ addObjectReference(objectHandle);
+ }
+
+ protected void addObjectReference(final long objectHandle) throws Error {
+ this.objectHandle = objectHandle;
+ try {
+ v8.addObjRef(this);
+ } catch (Error e) {
+ release();
+ throw e;
+ } catch (RuntimeException e) {
+ release();
+ throw e;
+ }
+ }
+
+
+ /**
+ * 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";
+ case INTEGER:
+ return "Integer";
+ case DOUBLE:
+ return "Double";
+ case BOOLEAN:
+ return "Boolean";
+ case STRING:
+ return "String";
+ case V8_ARRAY:
+ return "V8Array";
+ case V8_OBJECT:
+ return "V8Object";
+ case V8_FUNCTION:
+ return "V8Function";
+ case V8_TYPED_ARRAY:
+ return "V8TypedArray";
+ case BYTE:
+ return "Byte";
+ case V8_ARRAY_BUFFER:
+ return "V8ArrayBuffer";
+ case UNSIGNED_INT_8_ARRAY:
+ return "UInt8Array";
+ case UNSIGNED_INT_8_CLAMPED_ARRAY:
+ return "UInt8ClampedArray";
+ case INT_16_ARRAY:
+ return "Int16Array";
+ case UNSIGNED_INT_16_ARRAY:
+ return "UInt16Array";
+ case UNSIGNED_INT_32_ARRAY:
+ return "UInt32Array";
+ case FLOAT_32_ARRAY:
+ return "Float32Array";
+ case UNDEFINED:
+ return "Undefined";
+ default:
+ throw new IllegalArgumentException("Invalid V8 type: " + type);
+ }
+ }
+
+ /**
+ * Returns a constructor name of the V8 Value.
+ *
+ * @return The V8Value constructor name as a string.
+ */
+ public String getConstructorName() {
+ v8.checkThread();
+ v8.checkReleased();
+ return v8.getConstructorName(v8.getV8RuntimePtr(), objectHandle);
+ }
+
+ /**
+ * Determines if this value is undefined.
+ *
+ * @return Returns true if the value is undefined, false otherwise
+ */
+ public boolean isUndefined() {
+ return false;
+ }
+
+ /**
+ * Gets the runtime this Value was created on.
+ *
+ * @return Returns the V8 runtime this value is associated with.
+ */
+ public V8 getRuntime() {
+ 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
+ * changing existing ones) then both the original and twin
+ * will be updated. Twins are .equal and .strict equals, but
+ * not == in Java.
+ *
+ * Twins must be closed separately since they have their own
+ * native resources.
+ *
+ * @return A new Java object pointing at the same V8 Value
+ * as this.
+ */
+ public V8Value twin() {
+ if (isUndefined()) {
+ return this;
+ }
+ v8.checkThread();
+ v8.checkReleased();
+ V8Value twin = createTwin();
+ v8.createTwin(this, twin);
+ return twin;
+ }
+
+ /**
+ * 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 close() {
+ v8.checkThread();
+ if (!released) {
+ try {
+ v8.releaseObjRef(this);
+ } finally {
+ released = true;
+ v8.release(v8.getV8RuntimePtr(), objectHandle);
+ }
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @return Returns true if this object has been released, false otherwise.
+ */
+ public boolean isReleased() {
+ return released;
+ }
+
+ /**
+ * Performs a JS === on the parameter and the receiver.
+ *
+ * @param that The Object to compare this object against.
+ * @return Returns true iff this === that
+ */
+ public boolean strictEquals(final Object that) {
+ v8.checkThread();
+ checkReleased();
+ if (that == this) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (!(that instanceof V8Value)) {
+ return false;
+ }
+ if (isUndefined() && ((V8Value) that).isUndefined()) {
+ return true;
+ }
+ if (((V8Value) that).isUndefined()) {
+ return false;
+ }
+ return v8.strictEquals(v8.getV8RuntimePtr(), getHandle(), ((V8Value) that).getHandle());
+ }
+
+ protected long getHandle() {
+ checkReleased();
+ return objectHandle;
+ }
+
+ protected abstract V8Value createTwin();
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object that) {
+ return strictEquals(that);
+ }
+
+ /**
+ * Performs a JS == on the parameter and the receiver.
+ *
+ * @param that The Object to compare this object against.
+ * @return Returns true iff this == that
+ */
+ public boolean jsEquals(final Object that) {
+ v8.checkThread();
+ checkReleased();
+ if (that == this) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (!(that instanceof V8Value)) {
+ return false;
+ }
+ if (isUndefined() && ((V8Value) that).isUndefined()) {
+ return true;
+ }
+ if (((V8Value) that).isUndefined()) {
+ return false;
+ }
+ return v8.equals(v8.getV8RuntimePtr(), getHandle(), ((V8Value) that).getHandle());
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ v8.checkThread();
+ checkReleased();
+ return v8.identityHash(v8.getV8RuntimePtr(), getHandle());
+ }
+
+ protected void checkReleased() {
+ if (released) {
+ throw new IllegalStateException("Object released");
+ }
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/ArrayBuffer.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/ArrayBuffer.java
new file mode 100644
index 000000000..d1a39b8ec
--- /dev/null
+++ b/fine-j2v8/src/main/java/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();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java
new file mode 100644
index 000000000..34b3be25b
--- /dev/null
+++ b/fine-j2v8/src/main/java/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 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.
+ *
+ * Note: 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.
+ *
+ * Note: 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();
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java
new file mode 100644
index 000000000..7f236ae56
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.eclipsesource.v8.ReferenceHandler;
+import com.eclipsesource.v8.V8;
+import com.eclipsesource.v8.V8Value;
+
+/**
+ * A memory manager that tracks all V8 Handles while the object is registered.
+ * Once released, all V8 handles that were created while the memory manager
+ * was active, will be released.
+ *
+ * It is important that no V8 handles (V8Objects, V8Arrays, etc...) that are
+ * created while the memory manager is active, are persisted.
+ *
+ */
+public class MemoryManager {
+
+ private MemoryManagerReferenceHandler memoryManagerReferenceHandler;
+ private V8 v8;
+ private ArrayList references = new ArrayList();
+ private boolean releasing = false;
+ private boolean released = false;
+
+ /**
+ * Creates and registered a Memory Manager. After this, all V8 handles will be
+ * tracked until release is called.
+ *
+ * @param v8 The V8 runtime to register this Memory Manager on
+ */
+ public MemoryManager(final V8 v8) {
+ this.v8 = v8;
+ memoryManagerReferenceHandler = new MemoryManagerReferenceHandler();
+ v8.addReferenceHandler(memoryManagerReferenceHandler);
+ }
+
+ /**
+ * Returns the number of handles currently being tracked by this
+ * memory manager.
+ *
+ * Throws an IllegalStateException if the memory manager is used after it's
+ * been released.
+ *
+ * @return The object reference count
+ */
+ public int getObjectReferenceCount() {
+ checkReleased();
+ return references.size();
+ }
+
+ /**
+ * Persist an object that is currently being managed by this Manager.
+ *
+ * Objects that are being managed by a MemoryManager will be released
+ * once the MemoryManager is released. If an object is persisted, it will
+ * be remove from the MemoryManager's control and therefore will not
+ * be released.
+ *
+ * @param object The object to persist
+ */
+ public void persist(final V8Value object) {
+ v8.getLocker().checkThread();
+ checkReleased();
+ references.remove(object);
+ }
+
+ /**
+ * Checks if the memory manager has been released or not. Released memory
+ * managers can no longer be used.
+ *
+ * @return True if this memory manager has been released, false otherwise.
+ */
+ public boolean isReleased() {
+ return released;
+ }
+
+ /**
+ * Releases this Memory Manager and all V8Objects that were created while
+ * this memory manager was active.
+ */
+ public void release() {
+ v8.getLocker().checkThread();
+ if (released) {
+ return;
+ }
+ releasing = true;
+ try {
+ for (V8Value reference : references) {
+ reference.close();
+ }
+ v8.removeReferenceHandler(memoryManagerReferenceHandler);
+ references.clear();
+ } finally {
+ releasing = false;
+ }
+ released = true;
+ }
+
+ private void checkReleased() {
+ if (released) {
+ throw new IllegalStateException("Memory manager released");
+ }
+ }
+
+ private class MemoryManagerReferenceHandler implements ReferenceHandler {
+
+ @Override
+ public void v8HandleCreated(final V8Value object) {
+ references.add(object);
+ }
+
+ @Override
+ public void v8HandleDisposed(final V8Value object) {
+ if (!releasing) {
+ Iterator iterator = references.iterator();
+ while (iterator.hasNext()) {
+ if (iterator.next() == object) {
+ iterator.remove();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/SingleTypeAdapter.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/SingleTypeAdapter.java
new file mode 100644
index 000000000..d8efca58d
--- /dev/null
+++ b/fine-j2v8/src/main/java/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);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/TypeAdapter.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/TypeAdapter.java
new file mode 100644
index 000000000..7bae5eb2f
--- /dev/null
+++ b/fine-j2v8/src/main/java/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);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/TypedArray.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/TypedArray.java
new file mode 100644
index 000000000..1c1616ab7
--- /dev/null
+++ b/fine-j2v8/src/main/java/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();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java
new file mode 100644
index 000000000..1227bcb92
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import java.util.LinkedList;
+
+import com.eclipsesource.v8.JavaVoidCallback;
+import com.eclipsesource.v8.Releasable;
+import com.eclipsesource.v8.V8;
+import com.eclipsesource.v8.V8Array;
+import com.eclipsesource.v8.V8Object;
+
+/**
+ * Executes a JS Script on a new V8 runtime in its own thread, and once finished,
+ * will optionally wait on a message queue. If the executor is *not* long running,
+ * when the JS Script finishes, the executor will shutdown. If the executor
+ * *is* long running, the the script will execute, and when finished, the executor
+ * will wait for messages to arrive. When messages arrive, the messageHandler
+ * will be invoked with the contents of the message.
+ *
+ * Executors can be shutdown in two different ways. forceTermination() will
+ * stop any executing scripts and immediately terminate the executor. shutdown()
+ * will indicate that the executor should shutdown, but this will only happen
+ * once any scripts finish executing and the message queue becomes empty.
+ */
+public class V8Executor extends Thread {
+
+ private final String script;
+ private V8 runtime;
+ private String result;
+ private volatile boolean terminated = false;
+ private volatile boolean shuttingDown = false;
+ private volatile boolean forceTerminating = false;
+ private Exception exception = null;
+ private LinkedList messageQueue = new LinkedList();
+ private boolean longRunning;
+ private String messageHandler;
+
+ /**
+ * Create a new executor and execute the given script on it. Once
+ * the script has finished executing, the executor can optionally
+ * wait on a message queue.
+ *
+ * @param script The script to execute on this executor.
+ * @param longRunning True to indicate that this executor should be longRunning.
+ * @param messageHandler The name of the message handler that should be notified
+ * when messages are delivered.
+ */
+ public V8Executor(final String script, final boolean longRunning, final String messageHandler) {
+ this.script = script;
+ this.longRunning = longRunning;
+ this.messageHandler = messageHandler;
+ }
+
+ /**
+ * Create a new executor and execute the given script on it.
+ *
+ * @param script The script to execute on this executor.
+ */
+ public V8Executor(final String script) {
+ this(script, false, null);
+ }
+
+ /**
+ * Override to provide a custom setup for this V8 runtime.
+ * This method can be overridden to configure the V8 runtime,
+ * for example, to add callbacks or to add some additional
+ * functionality to the global scope.
+ *
+ * @param runtime The runtime to configure.
+ */
+ protected void setup(final V8 runtime) {
+
+ }
+
+ /**
+ * Gets the result of the JavaScript that was executed
+ * on this executor.
+ *
+ * @return The result of the JS Script that was executed on
+ * this executor.
+ */
+ public String getResult() {
+ return result;
+ }
+
+ /**
+ * Posts a message to the receiver to be processed by the executor
+ * and sent to the V8 runtime via the messageHandler.
+ *
+ * @param message The message to send to the messageHandler
+ */
+ public void postMessage(final String... message) {
+ synchronized (this) {
+ messageQueue.add(message);
+ notify();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Thread#run()
+ */
+ @Override
+ public void run() {
+ synchronized (this) {
+ runtime = V8.createV8Runtime();
+ runtime.registerJavaMethod(new ExecutorTermination(), "__j2v8__checkThreadTerminate");
+ setup(runtime);
+ }
+ try {
+ if (!forceTerminating) {
+ Object scriptResult = runtime.executeScript("__j2v8__checkThreadTerminate();\n" + script, getName(), -1);
+ if (scriptResult != null) {
+ result = scriptResult.toString();
+ }
+ if (scriptResult instanceof Releasable) {
+ ((Releasable) scriptResult).release();
+ }
+ }
+ while (!forceTerminating && longRunning) {
+ synchronized (this) {
+ if (messageQueue.isEmpty() && !shuttingDown) {
+ wait();
+ }
+ if ((messageQueue.isEmpty() && shuttingDown) || forceTerminating) {
+ return;
+ }
+ }
+ if (!messageQueue.isEmpty()) {
+ String[] message = messageQueue.remove(0);
+ V8Array parameters = new V8Array(runtime);
+ V8Array strings = new V8Array(runtime);
+ try {
+ for (String string : message) {
+ strings.push(string);
+ }
+ parameters.push(strings);
+ runtime.executeVoidFunction(messageHandler, parameters);
+ } finally {
+ strings.close();
+ parameters.close();
+ }
+ }
+ }
+ } catch (Exception e) {
+ exception = e;
+ } finally {
+ synchronized (this) {
+ if (runtime.getLocker().hasLock()) {
+ runtime.close();
+ runtime = null;
+ }
+ terminated = true;
+ }
+ }
+ }
+
+ /**
+ * Determines if an exception was thrown during the JavaScript execution.
+ *
+ * @return True if an exception was thrown during the JavaScript execution,
+ * false otherwise.
+ */
+ public boolean hasException() {
+ return exception != null;
+ }
+
+ /**
+ * Gets the exception that was thrown during the JavaScript execution.
+ *
+ * @return The exception that was thrown during the JavaScript execution,
+ * or null if no such exception was thrown.
+ */
+ public Exception getException() {
+ return exception;
+ }
+
+ /**
+ * Determines if the executor has terminated.
+ *
+ * @return True if the executor has terminated, false otherwise.
+ */
+ public boolean hasTerminated() {
+ return terminated;
+ }
+
+ /**
+ * Forces the executor to shutdown immediately. Any currently executing
+ * JavaScript will be interrupted and all outstanding messages will be
+ * ignored.
+ */
+ public void forceTermination() {
+ synchronized (this) {
+ forceTerminating = true;
+ shuttingDown = true;
+ if (runtime != null) {
+ runtime.terminateExecution();
+ }
+ notify();
+ }
+ }
+
+ /**
+ * Indicates to the executor that it should shutdown. Any currently
+ * executing JavaScript will be allowed to finish, and any outstanding
+ * messages will be processed. Only once the message queue is empty,
+ * will the executor actually shtutdown.
+ */
+ public void shutdown() {
+ synchronized (this) {
+ shuttingDown = true;
+ notify();
+ }
+ }
+
+ /**
+ * Returns true if shutdown() or forceTermination() was called to
+ * shutdown this executor.
+ *
+ * @return True if shutdown() or forceTermination() was called, false otherwise.
+ */
+ public boolean isShuttingDown() {
+ return shuttingDown;
+ }
+
+ /**
+ * Returns true if forceTermination was called to shutdown
+ * this executor.
+ *
+ * @return True if forceTermination() was called, false otherwise.
+ */
+ public boolean isTerminating() {
+ return forceTerminating;
+ }
+
+ class ExecutorTermination implements JavaVoidCallback {
+ @Override
+ public void invoke(final V8Object receiver, final V8Array parameters) {
+ if (forceTerminating) {
+ throw new RuntimeException("V8Thread Termination");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Map.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Map.java
new file mode 100644
index 000000000..4e0ddb925
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Map.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.eclipsesource.v8.Releasable;
+import com.eclipsesource.v8.V8Value;
+
+/**
+ * A Map that maps V8Values to arbitrary Java Objects.
+ * Once stored in the map, the keys (V8Values) can be released
+ * as the map will handle their resource management for you.
+ *
+ * Once the map is no longer needed, it should be released. To
+ * tie a map to the lifecycle of a V8 runtime, it can be registered
+ * as a resource with V8.registerResource.
+ */
+public class V8Map implements Map, Releasable {
+
+ private Map map;
+ private Map twinMap;
+
+ /**
+ * Creates a V8Map.
+ */
+ public V8Map() {
+ map = new HashMap();
+ twinMap = new HashMap();
+ }
+
+ /*
+ * (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() {
+ close();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#size()
+ */
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#isEmpty()
+ */
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ @Override
+ public boolean containsKey(final Object key) {
+ return map.containsKey(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ @Override
+ public boolean containsValue(final Object value) {
+ return map.containsValue(value);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ @Override
+ public V get(final Object key) {
+ return map.get(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public V put(final V8Value key, final V value) {
+ this.remove(key);
+ V8Value twin = key.twin();
+ twinMap.put(twin, twin);
+ return map.put(twin, value);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ @Override
+ public V remove(final Object key) {
+ V result = map.remove(key);
+ V8Value twin = twinMap.remove(key);
+ if (twin != null) {
+ twin.close();
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ @Override
+ public void putAll(final Map extends V8Value, ? extends V> m) {
+ for (Entry extends V8Value, ? extends V> entry : m.entrySet()) {
+ this.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#clear()
+ */
+ @Override
+ public void clear() {
+ map.clear();
+ for (V8Value V8Value : twinMap.keySet()) {
+ V8Value.close();
+ }
+ twinMap.clear();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#keySet()
+ */
+ @Override
+ public Set keySet() {
+ return map.keySet();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#values()
+ */
+ @Override
+ public Collection values() {
+ return map.values();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#entrySet()
+ */
+ @Override
+ public Set> entrySet() {
+ return map.entrySet();
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java
new file mode 100644
index 000000000..b5edac215
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+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;
+
+/**
+ * A set of static helper methods to convert V8Objects / V8Arrays to
+ * java.util Maps and Lists and back again. These conversions
+ * perform a deep copy.
+ */
+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 cache = new V8Map();
+ 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
+ * in the V8Object are released after they are accessed. However, the root
+ * object itself is not released.
+ *
+ * @param object The root of the V8Object graph.
+ * @return A map representing a deep copy of the V8Object rooted at 'object'.
+ */
+ public static Map 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 toMap(final V8Object object, final TypeAdapter adapter) {
+ V8Map cache = new V8Map();
+ try {
+ return toMap(object, cache, adapter);
+ } finally {
+ cache.close();
+ }
+ }
+
+ /**
+ * Creates a List from a V8Array using a deep copy. 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.
+ * @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 cache = new V8Map();
+ try {
+ return toList(array, cache, adapter);
+ } finally {
+ cache.close();
+ }
+ }
+
+ /**
+ * Populates a Java array from a V8Array. The type of the array must be specified.
+ * Currently, only INTEGER, DOUBLE, BOOLEAN and STRING are supported.
+ * The V8Array must only contain elements of type 'arrayType'. The result
+ * can be optionally passed in as a parameter.
+ *
+ * This method will use J2V8's bulk array copy making it faster than iterating over
+ * all the elements in the array.
+ *
+ * @param array The V8Array to convert to a Java Array.
+ * @param arrayType The type of the V8Array to convert.
+ * @param result The array to use as the result. If null, a new array will be created.
+ * @return A Java array representing a V8Array.
+ */
+ public static Object getTypedArray(final V8Array array, final int arrayType, final Object result) {
+ int length = array.length();
+ if (arrayType == V8Value.INTEGER) {
+ int[] intArray = (int[]) result;
+ if ((intArray == null) || (intArray.length < length)) {
+ intArray = new int[length];
+ }
+ array.getIntegers(0, length, intArray);
+ return intArray;
+ } else if (arrayType == V8Value.DOUBLE) {
+ double[] doubleArray = (double[]) result;
+ if ((doubleArray == null) || (doubleArray.length < length)) {
+ doubleArray = new double[length];
+ }
+ array.getDoubles(0, length, doubleArray);
+ return doubleArray;
+ } else if (arrayType == V8Value.BOOLEAN) {
+ boolean[] booleanArray = (boolean[]) result;
+ if ((booleanArray == null) || (booleanArray.length < length)) {
+ booleanArray = new boolean[length];
+ }
+ array.getBooleans(0, length, booleanArray);
+ return booleanArray;
+ } else if (arrayType == V8Value.STRING) {
+ String[] stringArray = (String[]) result;
+ if ((stringArray == null) || (stringArray.length < length)) {
+ stringArray = new String[length];
+ }
+ array.getStrings(0, length, stringArray);
+ return stringArray;
+ } else if (arrayType == V8Value.BYTE) {
+ byte[] byteArray = (byte[]) result;
+ if ((byteArray == null) || (byteArray.length < length)) {
+ byteArray = new byte[length];
+ }
+ array.getBytes(0, length, byteArray);
+ return byteArray;
+ }
+ throw new RuntimeException("Unsupported bulk load type: " + arrayType);
+ }
+
+ /**
+ * Creates a Java array from a V8Array. The type of the Array must be specified.
+ * Currently, only INTEGER, DOUBLE, BOOLEAN and STRING are supported.
+ * The V8Array must only contain elements of type 'arrayType'.
+ *
+ * This method will use J2V8's bulk array copy making it faster than iterating over
+ * all the elements in the array.
+ *
+ * @param array The V8Array to convert to a Java Array.
+ * @param arrayType The type of the V8Array to convert.
+ * @return A Java array representing a V8Array.
+ */
+ public static Object getTypedArray(final V8Array array, final int arrayType) {
+ int length = array.length();
+ if (arrayType == V8Value.INTEGER) {
+ return array.getIntegers(0, length);
+ } else if (arrayType == V8Value.DOUBLE) {
+ return array.getDoubles(0, length);
+ } else if (arrayType == V8Value.BOOLEAN) {
+ return array.getBooleans(0, length);
+ } else if (arrayType == V8Value.STRING) {
+ return array.getStrings(0, length);
+ }
+ throw new RuntimeException("Unsupported bulk load type: " + arrayType);
+ }
+
+ /**
+ * Creates a V8Object from a java.util.Map. This is a deep copy, so if the map
+ * contains other maps (or lists) they will also be converted.
+ *
+ * @param v8 The runtime on which to create the result.
+ * @param map The map to convert to a V8Object.
+ * @return A V8Object representing the map.
+ */
+ public static V8Object toV8Object(final V8 v8, final Map map) {
+ Map cache = new Hashtable();
+ try {
+ return toV8Object(v8, map, cache).twin();
+ } finally {
+ for (V8Value v8Object : cache.values()) {
+ v8Object.close();
+ }
+ }
+ }
+
+ /**
+ * Creates a V8Array from a java.util.List. This is a deep copy, so if the list
+ * contains other lists (or maps) they will also be converted.
+ *
+ * @param v8 The runtime on which to create the result.
+ * @param list The list to convert to a V8Array.
+ * @return A V8Array representing the list.
+ */
+ public static V8Array toV8Array(final V8 v8, final List extends Object> list) {
+ Map cache = new Hashtable();
+ try {
+ return toV8Array(v8, list, cache).twin();
+ } finally {
+ for (V8Value v8Object : cache.values()) {
+ v8Object.close();
+ }
+ }
+ }
+
+ /**
+ * Returns an object usable with a V8 Runtime which represents
+ * the parameter 'value'. If 'value' is an Integer, Boolean, Double
+ * or String, then 'value' is simply returned as these are directly
+ * usable on V8. If 'value' is a map / list, then it's converted to
+ * a V8Object / V8Array first.
+ *
+ * If the result is a V8Value, it must be released.
+ *
+ * @param v8 The runtime on which to create V8Values.
+ * @param value The value to convert to an object usable with V8
+ * @return An object which can be used directly with a V8 runtime.
+ */
+ public static Object getV8Result(final V8 v8, final Object value) {
+ if (value == null) {
+ return null;
+ }
+ Map cache = new Hashtable();
+ try {
+ Object result = getV8Result(v8, value, cache);
+ if (result instanceof V8Value) {
+ return ((V8Value) result).twin();
+ }
+ return result;
+ } finally {
+ for (V8Value v8Object : cache.values()) {
+ v8Object.close();
+ }
+ }
+ }
+
+ /**
+ * Pushes a Java Object to a V8Array by first converting it to a V8Value if needed.
+ * If the value is a boxed primitive, then the primitive will be pushed. If the object
+ * is a Map / List then a deep copy will be performed, converting the object to a
+ * V8Object / V8Array first.
+ *
+ * @param v8 The runtime on which to create any needed V8Values.
+ * @param array The array to push the elements to.
+ * @param value The value to push to the array.
+ */
+ public static void pushValue(final V8 v8, final V8Array array, final Object value) {
+ Map cache = new Hashtable();
+ try {
+ pushValue(v8, array, value, cache);
+ } finally {
+ for (V8Value v8Object : cache.values()) {
+ v8Object.close();
+ }
+ }
+ }
+
+ /**
+ * Gets a Java Object representing the value at the given index in the V8Array.
+ * 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.
+ * @return A Java Object representing the value at a given index.
+ */
+ public static Object getValue(final V8Array array, final int index) {
+ V8Map cache = new V8Map();
+ Object object = null;
+ int type = V8Value.UNDEFINED;
+ try {
+ 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 {
+ 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 cache = new V8Map();
+ 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();
+ }
+ }
+
+ /**
+ * Gets a Java Object representing the value with the given key in the V8Object.
+ * 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 object The object on which to lookup the value. The object is not
+ * released.
+ * @param key The key to use to lookup the value.
+ * @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 cache = new V8Map();
+ Object object = null;
+ int type = V8Value.UNDEFINED;
+ try {
+ 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 {
+ if (object instanceof Releasable) {
+ ((Releasable) object).release();
+ }
+ cache.close();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Map toMap(final V8Object v8Object, final V8Map cache, final TypeAdapter adapter) {
+ if (v8Object == null) {
+ return Collections.emptyMap();
+ }
+ if (cache.containsKey(v8Object)) {
+ return (Map) cache.get(v8Object);
+ }
+ Map result = new V8PropertyMap();
+ cache.put(v8Object, result);
+ String[] keys = v8Object.getKeys();
+ for (String key : keys) {
+ 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 cache, final TypeAdapter adapter) {
+ if (array == null) {
+ return Collections.emptyList();
+ }
+ if (cache.containsKey(array)) {
+ return (List super Object>) cache.get(array);
+ }
+ List super Object> result = new ArrayList();
+ cache.put(array, result);
+ for (int i = 0; i < array.length(); i++) {
+ Object object = null;
+ int type = V8Value.UNDEFINED;
+ try {
+ object = array.get(i);
+ type = array.getType(i);
+ Object value = getValue(object, type, cache, adapter);
+ if (value != IGNORE) {
+ result.add(value);
+ }
+ } finally {
+ if (object instanceof Releasable) {
+ ((Releasable) object).release();
+ }
+ }
+ }
+ return result;
+ }
+
+ private static V8TypedArray toV8TypedArray(final V8 v8, final TypedArray typeArray, final Map 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 cache) {
+ if (cache.containsKey(arrayBuffer)) {
+ return (V8ArrayBuffer) cache.get(arrayBuffer);
+ }
+ V8ArrayBuffer result = arrayBuffer.getV8ArrayBuffer();
+ cache.put(arrayBuffer, result);
+ return result;
+ }
+
+ private static V8Object toV8Object(final V8 v8, final Map map, final Map cache) {
+ if (cache.containsKey(map)) {
+ return (V8Object) cache.get(map);
+ }
+ V8Object result = new V8Object(v8);
+ cache.put(map, result);
+ try {
+ for (Entry entry : map.entrySet()) {
+ setValue(v8, result, entry.getKey(), entry.getValue(), cache);
+ }
+ } catch (IllegalStateException e) {
+ result.close();
+ throw e;
+ }
+ return result;
+ }
+
+ private static V8Array toV8Array(final V8 v8, final List extends Object> list, final Map cache) {
+ if (cache.containsKey(new ListWrapper(list))) {
+ return (V8Array) cache.get(new ListWrapper(list));
+ }
+ V8Array result = new V8Array(v8);
+ cache.put(new ListWrapper(list), result);
+ try {
+ for (int i = 0; i < list.size(); i++) {
+ Object value = list.get(i);
+ pushValue(v8, result, value, cache);
+ }
+ } catch (IllegalStateException e) {
+ result.close();
+ throw e;
+ }
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Object getV8Result(final V8 v8, final Object value, final Map cache) {
+ if (cache.containsKey(value)) {
+ return cache.get(value);
+ }
+ if (value instanceof Map, ?>) {
+ return toV8Object(v8, (Map) value, cache);
+ } else if (value instanceof List>) {
+ return toV8Array(v8, (List extends Object>) value, cache);
+ } else if (value instanceof TypedArray) {
+ return toV8TypedArray(v8, (TypedArray) value, cache);
+ } else if (value instanceof ArrayBuffer) {
+ return toV8ArrayBuffer(v8, (ArrayBuffer) value, cache);
+ }
+ return value;
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes", "resource"})
+ private static void pushValue(final V8 v8, final V8Array result, final Object value, final Map cache) {
+ if (value == null) {
+ result.pushUndefined();
+ } else if (value instanceof Integer) {
+ result.push(value);
+ } else if (value instanceof Long) {
+ result.push(Double.valueOf((Long) value));
+ } else if (value instanceof Double) {
+ result.push(value);
+ } else if (value instanceof Float) {
+ result.push(value);
+ } else if (value instanceof String) {
+ result.push((String) value);
+ } else if (value instanceof Boolean) {
+ 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);
+ } else if (value instanceof List) {
+ V8Array array = toV8Array(v8, (List) value, cache);
+ result.push(array);
+ } else {
+ throw new IllegalStateException("Unsupported Object of type: " + value.getClass());
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes", "resource"})
+ private static void setValue(final V8 v8, final V8Object result, final String key, final Object value, final Map 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, (Long) value);
+ } else if (value instanceof Double) {
+ result.add(key, (Double) value);
+ } else if (value instanceof Float) {
+ result.add(key, (Float) value);
+ } else if (value instanceof String) {
+ result.add(key, (String) value);
+ } else if (value instanceof Boolean) {
+ result.add(key, (Boolean) value);
+ } else if (value instanceof 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);
+ } else if (value instanceof List) {
+ V8Array array = toV8Array(v8, (List) value, cache);
+ result.add(key, array);
+ } else {
+ throw new IllegalStateException("Unsupported Object of type: " + value.getClass());
+ }
+ }
+
+ private static Object getValue(final Object value, final int valueType, final V8Map cache, final TypeAdapter adapter) {
+ Object adapterResult = adapter.adapt(valueType, value);
+ if (TypeAdapter.DEFAULT != adapterResult) {
+ return adapterResult;
+ }
+ switch (valueType) {
+ case V8Value.INTEGER:
+ case V8Value.DOUBLE:
+ case V8Value.BOOLEAN:
+ case V8Value.STRING:
+ return value;
+ case V8Value.V8_FUNCTION:
+ return IGNORE;
+ case V8Value.V8_ARRAY_BUFFER:
+ return new ArrayBuffer((V8ArrayBuffer) value);
+ case V8Value.V8_TYPED_ARRAY:
+ return new TypedArray((V8TypedArray) value);
+ case V8Value.V8_ARRAY:
+ return toList((V8Array) value, cache, adapter);
+ case V8Value.V8_OBJECT:
+ return toMap((V8Object) value, cache, adapter);
+ case V8Value.NULL:
+ return null;
+ case V8Value.UNDEFINED:
+ return V8.getUndefined();
+ default:
+ throw new IllegalStateException("Cannot convert type " + V8Value.getStringRepresentation(valueType));
+ }
+ }
+
+ private 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;
+
+ public ListWrapper(final List extends Object> list) {
+ this.list = list;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof ListWrapper) {
+ return ((ListWrapper) obj).list == list;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(list);
+ }
+ }
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java
new file mode 100644
index 000000000..a5d159d00
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A custom map is needed because the existing HashMaps
+ * do not allow self containment, and Hashtables do not
+ * allow nulls as values.
+ *
+ * This class is not considered API.
+ */
+class V8PropertyMap implements Map {
+
+ private Hashtable map = new Hashtable();
+ private Set nulls = new HashSet();
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#size()
+ */
+ @Override
+ public int size() {
+ return map.size() + nulls.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#isEmpty()
+ */
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty() && nulls.isEmpty();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ @Override
+ public boolean containsKey(final Object key) {
+ return map.containsKey(key) || nulls.contains(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ @Override
+ public boolean containsValue(final Object value) {
+ if ((value == null) && !nulls.isEmpty()) {
+ return true;
+ } else if (value == null) {
+ return false;
+ }
+ return map.containsValue(value);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ @Override
+ public V get(final Object key) {
+ if (nulls.contains(key)) {
+ return null;
+ }
+ return map.get(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public V put(final String key, final V value) {
+ if (value == null) {
+ if (map.containsKey(key)) {
+ map.remove(key);
+ }
+ nulls.add(key);
+ return null;
+ }
+ if (nulls.contains(key)) {
+ nulls.remove(key);
+ }
+ return map.put(key, value);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ @Override
+ public V remove(final Object key) {
+ if (nulls.contains(key)) {
+ nulls.remove(key);
+ return null;
+ }
+ return map.remove(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ @Override
+ public void putAll(final Map extends String, ? extends V> m) {
+ for (Entry extends String, ? extends V> entry : m.entrySet()) {
+ this.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#clear()
+ */
+ @Override
+ public void clear() {
+ map.clear();
+ nulls.clear();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#keySet()
+ */
+ @Override
+ public Set keySet() {
+ HashSet result = new HashSet(map.keySet());
+ result.addAll(nulls);
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#values()
+ */
+ @Override
+ public Collection values() {
+ ArrayList result = new ArrayList(map.values());
+ for (int i = 0; i < nulls.size(); i++) {
+ result.add(null);
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.Map#entrySet()
+ */
+ @Override
+ public Set> entrySet() {
+ HashSet> result = new HashSet>(map.entrySet());
+ for (String nullKey : nulls) {
+ result.add(new SimpleEntry(nullKey, null));
+ }
+ return result;
+ }
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Runnable.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Runnable.java
new file mode 100644
index 000000000..7df197a5b
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Runnable.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import com.eclipsesource.v8.V8;
+
+/**
+ * Classes can implement this interface to execute arbitrary code on
+ * isolated V8 runtime on its own thread. Instances of classes that
+ * implement this interface can be passed to V8Thread.
+ */
+public interface V8Runnable {
+
+ /**
+ * Execute the code on the provided runtime.
+ *
+ * @param runtime The V8 runtime assigned to this runnable.
+ */
+ public void run(final V8 runtime);
+
+}
diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Thread.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Thread.java
new file mode 100644
index 000000000..0233ffb65
--- /dev/null
+++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Thread.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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;
+
+import com.eclipsesource.v8.V8;
+
+/**
+ * A Thread with its own V8 runtime. The thread will create a runtime,
+ * and execute a runnable on that runtime. When the thread ends,
+ * the runtime will be released.
+ *
+ * It's suggested that you *DO NOT* release the lock on the runtime.
+ * If the lock is released, you will need to ensure that the runtime
+ * is properly released.
+ */
+public class V8Thread extends Thread {
+
+ private final V8Runnable target;
+ private V8 runtime;
+
+ /**
+ * Create as new Thread with its own V8Runtime.
+ *
+ * @param target The code to execute with the given runtime.
+ */
+ public V8Thread(final V8Runnable target) {
+ this.target = target;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Thread#run()
+ */
+ @Override
+ public void run() {
+ runtime = V8.createV8Runtime();
+ try {
+ target.run(runtime);
+ } finally {
+ synchronized (this) {
+ if (runtime.getLocker().hasLock()) {
+ runtime.close();
+ runtime = null;
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so b/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so
new file mode 100644
index 000000000..19c95ad78
Binary files /dev/null and b/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so differ
diff --git a/fine-j2v8/src/main/resources/libj2v8-macosx-aarch_64.dylib b/fine-j2v8/src/main/resources/libj2v8-macosx-aarch_64.dylib
new file mode 100644
index 000000000..d38c3d088
Binary files /dev/null and b/fine-j2v8/src/main/resources/libj2v8-macosx-aarch_64.dylib differ
diff --git a/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib b/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib
new file mode 100644
index 000000000..f12bbafa6
Binary files /dev/null and b/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib differ
diff --git a/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll b/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll
new file mode 100644
index 000000000..bcb827091
Binary files /dev/null and b/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll differ
diff --git a/fine-skywalking-toolkit-trace/pom.xml b/fine-skywalking-toolkit-trace/pom.xml
new file mode 100644
index 000000000..8edbb52cb
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ com.fr.third
+ step1
+ ${revision}
+ ../base-third-project/base-third-step1
+
+ 4.0.0
+
+ fine-skywalking-toolkit-trace
+ jar
+
+ http://maven.apache.org
+
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ActiveSpan.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ActiveSpan.java
new file mode 100644
index 000000000..6954a40bc
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ActiveSpan.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+/**
+ * provide custom api that set tag for current active span.
+ */
+public class ActiveSpan {
+ /**
+ * @param key tag key
+ * @param value tag value
+ */
+ public static void tag(String key, String value) {
+ }
+
+ public static void error() {
+ }
+
+ public static void error(String errorMsg) {
+ }
+
+ public static void error(Throwable throwable) {
+ }
+
+ public static void debug(String debugMsg) {
+ }
+
+ public static void info(String infoMsg) {
+ }
+
+ public static void setOperationName(String operationName) {
+ }
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/CallableWrapper.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/CallableWrapper.java
new file mode 100644
index 000000000..3f5dd6921
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/CallableWrapper.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.util.concurrent.Callable;
+
+@TraceCrossThread
+public class CallableWrapper implements Callable {
+ final Callable callable;
+
+ public static CallableWrapper of(Callable r) {
+ return new CallableWrapper<>(r);
+ }
+
+ public CallableWrapper(Callable callable) {
+ this.callable = callable;
+ }
+
+ @Override
+ public V call() throws Exception {
+ return callable.call();
+ }
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ConsumerWrapper.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ConsumerWrapper.java
new file mode 100644
index 000000000..02ca8198e
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/ConsumerWrapper.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.util.function.Consumer;
+
+@TraceCrossThread
+public class ConsumerWrapper implements Consumer {
+ final Consumer consumer;
+
+ public ConsumerWrapper(Consumer consumer) {
+ this.consumer = consumer;
+ }
+
+ public static ConsumerWrapper of(Consumer consumer) {
+ return new ConsumerWrapper(consumer);
+ }
+
+ @Override
+ public void accept(V v) {
+ this.consumer.accept(v);
+ }
+
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/FunctionWrapper.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/FunctionWrapper.java
new file mode 100644
index 000000000..356c671f3
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/FunctionWrapper.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.util.function.Function;
+
+@TraceCrossThread
+public class FunctionWrapper implements Function {
+ final Function function;
+
+ public FunctionWrapper(Function function) {
+ this.function = function;
+ }
+
+ public static FunctionWrapper of(Function function) {
+ return new FunctionWrapper(function);
+ }
+
+ @Override
+ public R apply(T t) {
+ return this.function.apply(t);
+ }
+
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/IgnoredException.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/IgnoredException.java
new file mode 100644
index 000000000..372c25010
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/IgnoredException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * After the exception status checker activated in the agent, the span wouldn't be marked as error status if the
+ * exception has this annotation.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface IgnoredException {
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/RunnableWrapper.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/RunnableWrapper.java
new file mode 100644
index 000000000..25e204c64
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/RunnableWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+@TraceCrossThread
+public class RunnableWrapper implements Runnable {
+ final Runnable runnable;
+
+ public RunnableWrapper(Runnable runnable) {
+ this.runnable = runnable;
+ }
+
+ public static RunnableWrapper of(Runnable r) {
+ return new RunnableWrapper(r);
+ }
+
+ @Override
+ public void run() {
+ this.runnable.run();
+ }
+}
\ No newline at end of file
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/SupplierWrapper.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/SupplierWrapper.java
new file mode 100644
index 000000000..1f8ef2f92
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/SupplierWrapper.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.util.function.Supplier;
+
+@TraceCrossThread
+public class SupplierWrapper implements Supplier {
+ final Supplier supplier;
+
+ public static SupplierWrapper of(Supplier r) {
+ return new SupplierWrapper<>(r);
+ }
+
+ public SupplierWrapper(Supplier supplier) {
+ this.supplier = supplier;
+ }
+
+ @Override
+ public V get() {
+ return supplier.get();
+ }
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tag.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tag.java
new file mode 100644
index 000000000..22917d42f
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tag.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Tag the current active span with key {@link #key()} and value {@link #value()}, if there is no active span, this
+ * annotation takes no effect.
+ *
+ * @see Tags
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(Tags.class)
+public @interface Tag {
+ /**
+ * @return the key of the tag to be injected into the current active span
+ */
+ String key();
+
+ /**
+ * @return the value of the tag to be injected into the current active span, in the form of the customized
+ * enhancement rules, for more information, refer to https://github.com/apache/skywalking/blob/master/docs/en/setup/service-agent/java-agent/Customize-enhance-trace.md#how-to-configure
+ */
+ String value();
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tags.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tags.java
new file mode 100644
index 000000000..b59707158
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Tags.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A wrapper annotation for {@link Tag} that allows to apply multiple tags to a single method span,
+ *
+ *
+ * @Tag(key = "tag1", value = "arg[0]")
+ * @Tag(key = "tag2", value = "arg[1]")
+ * public void test(String param1, String param2) {
+ * // ...
+ * }
+ *
+ *
+ * @see Tag
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Tags {
+ /**
+ * @see Tag
+ */
+ Tag[] value();
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Trace.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Trace.java
new file mode 100644
index 000000000..a06bdab29
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/Trace.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The agent create local span if the method that annotation with {@link Trace}. The value of span operation name will
+ * fetch by {@link #operationName()}. if the value of {@link #operationName()} is blank string. the operation name will
+ * be set the class name + method name.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Trace {
+ /**
+ * @return operation name, the default value is blank string.
+ */
+ String operationName() default "";
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java
new file mode 100644
index 000000000..dd191c16a
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.util.Optional;
+
+/**
+ * Try to access the sky-walking tracer context. The context is not existed, always. only the middleware, component, or
+ * rpc-framework are supported in the current invoke stack, in the same thread, the context will be available.
+ *
+ */
+public class TraceContext {
+
+ /**
+ * Try to get the traceId of current trace context.
+ *
+ * @return traceId, if it exists, or empty {@link String}.
+ */
+ public static String traceId() {
+ return "";
+ }
+
+ /**
+ * Try to get the segmentId of current trace context.
+ *
+ * @return segmentId, if it exists, or empty {@link String}.
+ */
+ public static String segmentId() {
+ return "";
+ }
+
+ /**
+ * Try to get the spanId of current trace context. The spanId is a negative number when the trace context is
+ * missing.
+ *
+ * @return spanId, if it exists, or empty {@link String}.
+ */
+ public static int spanId() {
+ return -1;
+ }
+
+ /**
+ * Try to get the custom value from trace context.
+ *
+ * @return custom data value.
+ */
+ public static Optional getCorrelation(String key) {
+ return Optional.empty();
+ }
+
+ /**
+ * Put the custom key/value into trace context.
+ *
+ * @return previous value if it exists.
+ */
+ public static Optional putCorrelation(String key, String value) {
+ return Optional.empty();
+ }
+
+}
diff --git a/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceCrossThread.java b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceCrossThread.java
new file mode 100644
index 000000000..e6049c61b
--- /dev/null
+++ b/fine-skywalking-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceCrossThread.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TraceCrossThread {
+
+}
\ No newline at end of file