From b9a78a1d4bdccca5050d2c0b86ad1fd0ad98c488 Mon Sep 17 00:00:00 2001 From: tianya8318 Date: Wed, 30 Aug 2023 21:47:55 +0800 Subject: [PATCH 01/10] Upgrade J2V8 to 00dddaa --- .../com/eclipsesource/v8/LibraryLoader.java | 160 +-- .../java/com/eclipsesource/v8/NodeJS.java | 10 +- .../java/com/eclipsesource/v8/Platform.java | 5 - .../eclipsesource/v8/PlatformDetector.java | 48 +- .../java/com/eclipsesource/v8/Releasable.java | 10 +- .../eclipsesource/v8/SignatureProvider.java | 5 + src/main/java/com/eclipsesource/v8/V8.java | 159 ++- .../java/com/eclipsesource/v8/V8Array.java | 9 + .../com/eclipsesource/v8/V8ArrayBuffer.java | 399 +++++- .../java/com/eclipsesource/v8/V8Function.java | 1 + .../java/com/eclipsesource/v8/V8Object.java | 17 +- .../com/eclipsesource/v8/V8TypedArray.java | 58 +- .../java/com/eclipsesource/v8/V8Value.java | 59 +- .../eclipsesource/v8/debug/DebugHandler.java | 43 +- .../com/eclipsesource/v8/debug/EventData.java | 10 +- .../v8/debug/ExecutionState.java | 16 +- .../v8/debug/ScriptBreakPoint.java | 11 +- .../eclipsesource/v8/debug/V8DebugServer.java | 32 +- .../eclipsesource/v8/debug/mirror/Frame.java | 24 +- .../v8/debug/mirror/FunctionMirror.java | 2 +- .../eclipsesource/v8/debug/mirror/Mirror.java | 18 +- .../v8/debug/mirror/ObjectMirror.java | 8 +- .../v8/debug/mirror/PropertiesArray.java | 20 +- .../v8/debug/mirror/PropertyMirror.java | 2 +- .../eclipsesource/v8/debug/mirror/Scope.java | 12 +- .../inspector/DebuggerConnectionListener.java | 7 + .../v8/inspector/V8Inspector.java | 67 + .../v8/inspector/V8InspectorDelegate.java | 7 + .../eclipsesource/v8/utils/ArrayBuffer.java | 69 + .../eclipsesource/v8/utils/ConcurrentV8.java | 2 +- .../eclipsesource/v8/utils/MemoryManager.java | 2 +- .../eclipsesource/v8/utils/TypedArray.java | 73 + .../eclipsesource/v8/utils/V8Executor.java | 9 +- .../com/eclipsesource/v8/utils/V8Map.java | 20 +- .../eclipsesource/v8/utils/V8ObjectUtils.java | 151 +- .../eclipsesource/v8/utils/V8PropertyMap.java | 2 +- .../com/eclipsesource/v8/utils/V8Thread.java | 2 +- .../v8/utils/typedarrays/ArrayBuffer.java | 118 -- .../v8/utils/typedarrays/Float32Array.java | 79 -- .../v8/utils/typedarrays/Float64Array.java | 79 -- .../v8/utils/typedarrays/Int16Array.java | 79 -- .../v8/utils/typedarrays/Int32Array.java | 75 - .../v8/utils/typedarrays/Int8Array.java | 78 - .../v8/utils/typedarrays/TypedArray.java | 58 - .../v8/utils/typedarrays/UInt16Array.java | 79 -- .../v8/utils/typedarrays/UInt32Array.java | 79 -- .../v8/utils/typedarrays/UInt8Array.java | 78 - .../utils/typedarrays/UInt8ClampedArray.java | 87 -- src/main/jni/com_eclipsesource_v8_V8Impl.cpp | 1259 +++++++++-------- src/main/jni/com_eclipsesource_v8_V8Impl.h | 58 +- 50 files changed, 1876 insertions(+), 1879 deletions(-) create mode 100644 src/main/java/com/eclipsesource/v8/SignatureProvider.java create mode 100644 src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java create mode 100644 src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java create mode 100644 src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java create mode 100644 src/main/java/com/eclipsesource/v8/utils/ArrayBuffer.java create mode 100644 src/main/java/com/eclipsesource/v8/utils/TypedArray.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/Float32Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/Float64Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/Int16Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/Int32Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/Int8Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/TypedArray.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java delete mode 100644 src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java diff --git a/src/main/java/com/eclipsesource/v8/LibraryLoader.java b/src/main/java/com/eclipsesource/v8/LibraryLoader.java index 6ffc07b..4fbf740 100644 --- a/src/main/java/com/eclipsesource/v8/LibraryLoader.java +++ b/src/main/java/com/eclipsesource/v8/LibraryLoader.java @@ -7,6 +7,7 @@ * * Contributors: * EclipseSource - initial API and implementation + * Wolfgang Steiner - code separation PlatformDetector/LibraryLoader ******************************************************************************/ package com.eclipsesource.v8; @@ -20,66 +21,93 @@ class LibraryLoader { static final String SEPARATOR; static final String DELIMITER; - // HYBRID MODIFY: - //static final String SWT_LIB_DIR = ".j2v8"; - static final String SWT_LIB_DIR = ".jsenv"; + static final String SWT_LIB_DIR = ".j2v8"; static { DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$ SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$ } - private static String computeLibraryShortName() { - // HYBRID MODIFY - //String base = "j2v8"; - String base = "jsenv"; - String osSuffix = getOS(); - String archSuffix = getArchSuffix(); - return base + "_" + osSuffix + "_" + archSuffix; - } + /** + * Returns the base-name for the native J2V8 library file. + * @param withLinuxVendor include/exclude the {vendor} part from the returned filename + *

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 = "-"; - private static String computeLibraryFullName() { - return "lib" + computeLibraryShortName() + "." + getOSFileExtension(); + return + prefix + + (vendor != null ? separator + vendor : "") + + separator + os + + separator + arch; } - static void loadLibrary(final String tempDirectory) { - if ( isAndroid() ) { - // HYBRID MODIFY: - //System.loadLibrary("j2v8"); - System.loadLibrary("jsenv"); - return; - } - StringBuffer message = new StringBuffer(); - String libShortName = computeLibraryShortName(); - String libFullName = computeLibraryFullName(); - String ideLocation = System.getProperty("user.dir") + SEPARATOR + "jni" + SEPARATOR + computeLibraryFullName(); + public static String computeLibraryFullName(boolean withLinuxVendor) { + return "lib" + computeLibraryShortName(withLinuxVendor) + "." + PlatformDetector.OS.getLibFileExtension(); + } - String path = null; + static boolean tryLoad(boolean withLinuxVendor, StringBuffer message) { + String libShortName = computeLibraryShortName(withLinuxVendor); + String libFullName = computeLibraryFullName(withLinuxVendor); + String ideLocation = System.getProperty("user.dir") + SEPARATOR + "jni" + SEPARATOR + libFullName; /* Try loading library from java library path */ if (load(libFullName, message)) { - return; + return true; } if (load(libShortName, message)) { - return; + return true; } /* Try loading library from the IDE location */ if (new File(ideLocation).exists()) { if (load(ideLocation, message)) { - return; + return true; } } + return false; + } + + static void loadLibrary(final String tempDirectory) { + if (PlatformDetector.OS.isAndroid()) { + System.loadLibrary("j2v8"); + return; + } + + StringBuffer message = new StringBuffer(); + + // try loading a vendor-specific library first + if (tryLoad(true, message)) + return; + + // if there is no vendor-specific library, just try to load the default OS library + if (tryLoad(false, message)) + return; + + String path = null; + if (tempDirectory != null) { path = tempDirectory; } else { path = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$ } - if (extract(path + SEPARATOR + libFullName, libFullName, message)) { + // try extracting a vendor-specific library first + if (extract(path, true, message)) + return; + + // if there is no vendor-specific library, just try to extract the default OS library + if (extract(path, false, message)) return; - } /* Failed to find the library */ throw new UnsatisfiedLinkError("Could not load J2V8 library. Reasons: " + message.toString()); //$NON-NLS-1$ @@ -104,6 +132,11 @@ static boolean load(final String libName, final StringBuffer message) { 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; @@ -150,7 +183,7 @@ static boolean extract(final String fileName, final String mappedName, final Str } static void chmod(final String permision, final String path) { - if (isWindows()) { + if (PlatformDetector.OS.isWindows()) { return; } try { @@ -158,69 +191,4 @@ static void chmod(final String permision, final String path) { } catch (Throwable e) { } } - - static String getOsName() { - return System.getProperty("os.name") + System.getProperty("java.specification.vendor"); - } - - static boolean isWindows() { - return getOsName().startsWith("Windows"); - } - - static boolean isMac() { - return getOsName().startsWith("Mac"); - } - - static boolean isLinux() { - return getOsName().startsWith("Linux"); - } - - static boolean isNativeClient() { - return getOsName().startsWith("nacl"); - } - - static boolean isAndroid() { - return getOsName().contains("Android"); - } - - static String getArchSuffix() { - String arch = System.getProperty("os.arch"); - if (arch.equals("i686")) { - return "x86"; - } else if (arch.equals("amd64")) { - return "x86_64"; - } else if (arch.equals("nacl")) { - return "armv7l"; - } else if (arch.equals("aarch64")) { - return "armv7l"; - } - return arch; - } - - static String getOSFileExtension() { - if (isWindows()) { - return "dll"; - } else if (isMac()) { - return "dylib"; - } else if (isLinux()) { - return "so"; - } else if (isNativeClient()) { - return "so"; - } - throw new UnsatisfiedLinkError("Unsupported platform: " + getOsName()); - } - - static String getOS() { - if (isWindows()) { - return "win32"; - } else if (isMac()) { - return "macosx"; - } else if (isLinux() && !isAndroid()) { - return "linux"; - } else if (isAndroid()) { - return "android"; - } - throw new UnsatisfiedLinkError("Unsupported platform: " + getOsName()); - } - } diff --git a/src/main/java/com/eclipsesource/v8/NodeJS.java b/src/main/java/com/eclipsesource/v8/NodeJS.java index 4655212..30d1483 100644 --- a/src/main/java/com/eclipsesource/v8/NodeJS.java +++ b/src/main/java/com/eclipsesource/v8/NodeJS.java @@ -91,7 +91,7 @@ public void invoke(final V8Object receiver, final V8Array parameters) { try { node.init(require.twin()); } finally { - require.release(); + require.close(); } } }, STARTUP_CALLBACK); @@ -137,10 +137,10 @@ public boolean handleMessage() { public void release() { v8.checkThread(); if (!require.isReleased()) { - require.release(); + require.close(); } if (!v8.isReleased()) { - v8.release(); + v8.close(); } } @@ -168,7 +168,7 @@ public V8Object require(final File file) { requireParams.push(file.getAbsolutePath()); return (V8Object) require.call(null, requireParams); } finally { - requireParams.release(); + requireParams.close(); } } @@ -205,7 +205,7 @@ public Object invoke(final V8Object receiver, final V8Array parameters) { requireParams.push(file.getAbsolutePath()); return require.call(null, requireParams); } finally { - requireParams.release(); + requireParams.close(); } } }); diff --git a/src/main/java/com/eclipsesource/v8/Platform.java b/src/main/java/com/eclipsesource/v8/Platform.java index cfde660..8168935 100644 --- a/src/main/java/com/eclipsesource/v8/Platform.java +++ b/src/main/java/com/eclipsesource/v8/Platform.java @@ -1,8 +1,3 @@ -/** - * Copyright (c) 2021, the hapjs-platform Project Contributors - * SPDX-License-Identifier: EPL-1.0 - */ - package com.eclipsesource.v8; public class Platform { diff --git a/src/main/java/com/eclipsesource/v8/PlatformDetector.java b/src/main/java/com/eclipsesource/v8/PlatformDetector.java index 10fdb76..0913c1a 100644 --- a/src/main/java/com/eclipsesource/v8/PlatformDetector.java +++ b/src/main/java/com/eclipsesource/v8/PlatformDetector.java @@ -29,21 +29,19 @@ import java.io.Closeable; import java.io.File; import java.io.FileInputStream; -import java.io.InputStreamReader; import java.io.IOException; -import java.util.HashMap; +import java.io.InputStreamReader; import java.util.Locale; -import com.eclipsesource.v8.Platform; - 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)) + if (archName.equals(Platform.UNKNOWN)) { throw new UnsatisfiedLinkError("Unsupported arch: " + archProperty); + } return archName; } @@ -62,8 +60,9 @@ public static String getName() { return Platform.ANDROID; } - if (osName.equals(Platform.UNKNOWN)) + if (osName.equals(Platform.UNKNOWN)) { throw new UnsatisfiedLinkError("Unsupported platform/vendor: " + osProperty + " / " + vendorProperty); + } return osName; } @@ -89,16 +88,19 @@ public static boolean isAndroid() { } public static String getLibFileExtension() { - if (isWindows()) + if (isWindows()) { return "dll"; + } - if (isMac()) + if (isMac()) { return "dylib"; + } if (isLinux() || isAndroid() - || isNativeClient()) + || isNativeClient()) { return "so"; + } throw new UnsatisfiedLinkError("Unsupported platform library-extension for: " + getName()); } @@ -110,14 +112,18 @@ public static class Vendor { private static final String LINUX_ID_PREFIX = "ID="; public static String getName() { - if (OS.isWindows()) + if (OS.isWindows()) { return "microsoft"; - if (OS.isMac()) + } + if (OS.isMac()) { return "apple"; - if (OS.isLinux()) + } + if (OS.isLinux()) { return getLinuxOsReleaseId(); - if (OS.isAndroid()) + } + if (OS.isAndroid()) { return "google"; + } throw new UnsatisfiedLinkError("Unsupported vendor: " + getName()); } @@ -141,7 +147,7 @@ private static String getLinuxOsReleaseId() { throw new UnsatisfiedLinkError("Unsupported linux vendor: " + getName()); } - private static String parseLinuxOsReleaseFile(File file) { + private static String parseLinuxOsReleaseFile(final File file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); @@ -166,7 +172,7 @@ private static String parseLinuxOsReleaseFile(File file) { return null; } - private static String parseLinuxRedhatReleaseFile(File file) { + private static String parseLinuxRedhatReleaseFile(final File file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); @@ -198,7 +204,7 @@ private static String parseLinuxRedhatReleaseFile(File file) { return null; } - private static void closeQuietly(Closeable obj) { + private static void closeQuietly(final Closeable obj) { try { if (obj != null) { obj.close(); @@ -209,7 +215,7 @@ private static void closeQuietly(Closeable obj) { } } - private static String normalizeOsReleaseValue(String value) { + private static String normalizeOsReleaseValue(final String value) { // Remove any quotes from the string. return value.trim().replace("\"", ""); } @@ -224,7 +230,7 @@ private static String normalizeOs(String value) { } if (value.startsWith("os400")) { // Avoid the names such as os4000 - if (value.length() <= 5 || !Character.isDigit(value.charAt(5))) { + if ((value.length() <= 5) || !Character.isDigit(value.charAt(5))) { return "os400"; } } @@ -276,10 +282,10 @@ private static String normalizeArch(String value) { if (value.matches("^(sparcv9|sparc64)$")) { return "sparc_64"; } - if (value.matches("^(arm|arm32)$")) { + if (value.matches("^(arm|arm32)$") || value.startsWith("armv7")) { return "arm_32"; } - if ("aarch64".equals(value)) { + if ("aarch64".equals(value) || value.startsWith("armv8")) { return "aarch_64"; } if (value.matches("^(ppc|ppc32)$")) { @@ -301,7 +307,7 @@ private static String normalizeArch(String value) { return Platform.UNKNOWN; } - private static String normalize(String value) { + private static String normalize(final String value) { if (value == null) { return ""; } diff --git a/src/main/java/com/eclipsesource/v8/Releasable.java b/src/main/java/com/eclipsesource/v8/Releasable.java index 0017787..3edee1e 100644 --- a/src/main/java/com/eclipsesource/v8/Releasable.java +++ b/src/main/java/com/eclipsesource/v8/Releasable.java @@ -10,15 +10,21 @@ ******************************************************************************/ package com.eclipsesource.v8; +import java.io.Closeable; + /** * An interface used to denote all V8 Classes which can be released. */ -public interface Releasable { +public interface Releasable extends Closeable { /** * Release the underlying resources. Once an object is released * it typically cannot be used again. */ - void release(); + void close(); + /** + * Synonym for {@link #close()}. + */ + void release(); } diff --git a/src/main/java/com/eclipsesource/v8/SignatureProvider.java b/src/main/java/com/eclipsesource/v8/SignatureProvider.java new file mode 100644 index 0000000..035c5b0 --- /dev/null +++ b/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/src/main/java/com/eclipsesource/v8/V8.java b/src/main/java/com/eclipsesource/v8/V8.java index 96db3b9..511f522 100644 --- a/src/main/java/com/eclipsesource/v8/V8.java +++ b/src/main/java/com/eclipsesource/v8/V8.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import com.eclipsesource.v8.inspector.V8InspectorDelegate; import com.eclipsesource.v8.utils.V8Executor; import com.eclipsesource.v8.utils.V8Map; import com.eclipsesource.v8.utils.V8Runnable; @@ -47,6 +48,7 @@ public class V8 extends V8Object { private Map data = null; private final V8Locker locker; + private SignatureProvider signatureProvider = null; private long objectReferences = 0; private long v8RuntimePtr = 0; private List resources = null; @@ -114,12 +116,6 @@ public static V8 createV8Runtime() { return createV8Runtime(null, null); } - // HYBRID ADD BEGIN - public static V8 createV8Runtime(final String globalAlias, final String tempDirectory) { - return createV8Runtime(globalAlias, tempDirectory, null); - } - // HYBRID END - /** * 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, @@ -148,10 +144,7 @@ public static V8 createV8Runtime(final String globalAlias) { * * @return A new isolated V8 Runtime. */ - // HYBRID MODIFY: - //public static V8 createV8Runtime(final String globalAlias, final String tempDirectory) { - public static V8 createV8Runtime(final String globalAlias, final String tempDirectory, - final String nativejsSnapshotSoName) { + public static V8 createV8Runtime(final String globalAlias, final String tempDirectory) { if (!nativeLibraryLoaded) { synchronized (lock) { if (!nativeLibraryLoaded) { @@ -164,15 +157,17 @@ public static V8 createV8Runtime(final String globalAlias, final String tempDire _setFlags(v8Flags); initialized = true; } - // HYBRID MODIFY: - //V8 runtime = new V8(globalAlias); - V8 runtime = new V8(globalAlias, nativejsSnapshotSoName); + 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. * @@ -260,12 +255,16 @@ private void notifyReferenceDisposed(final V8Value 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("J2V8 native library not loaded", nativeLoadError); + throw new IllegalStateException(message, nativeLoadError); } else if (nativeLoadException != null) { - throw new IllegalStateException("J2V8 native library not loaded", nativeLoadException); + throw new IllegalStateException(message, nativeLoadException); } else { - throw new IllegalStateException("J2V8 native library not loaded"); + throw new IllegalStateException(message); } } } @@ -274,24 +273,28 @@ protected V8() { this(null); } - // HYBRID MODIFY: - //protected V8(final String globalAlias) { - protected V8(final String globalAlias, final String nativejsSnapshotSoName) { + protected V8(final String globalAlias) { super(null); released = false; - // HYBRID MODIFY: - //v8RuntimePtr = _createIsolate(globalAlias); - v8RuntimePtr = _createIsolate(globalAlias, nativejsSnapshotSoName); + v8RuntimePtr = _createIsolate(globalAlias); locker = new V8Locker(this); checkThread(); objectHandle = _getGlobalObject(v8RuntimePtr); } - // HYBRID ADD BEGIN: - protected V8(final String globalAlias) { - this(globalAlias, null); + public long createInspector(final V8InspectorDelegate inspectorDelegate, final String contextName) { + return _createInspector(v8RuntimePtr, inspectorDelegate, contextName); + } + + 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); } - // HYBRID END /** * Returns an UNDEFINED constant. @@ -344,11 +347,21 @@ 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); } @@ -392,7 +405,7 @@ public void release(final boolean reportMemoryLeaks) { v8RuntimePtr = 0L; released = true; if (reportMemoryLeaks && (getObjectReferenceCount() > 0)) { - throw new IllegalStateException(objectReferences + " Object(s) still exist in runtime"); + throw new IllegalStateException(getObjectReferenceCount() + " Object(s) still exist in runtime"); } } } @@ -677,16 +690,51 @@ public Object executeScript(final String script) { * Primitives will be boxed. * * @param script The script to execute. - * @param scriptName The name of the script + * @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 scriptName, final int lineNumber) { + public Object executeScript(final String script, final String uri, final int lineNumber) { checkThread(); checkScript(script); - return executeScript(getV8RuntimePtr(), UNKNOWN, script, scriptName, lineNumber); + 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); } /** @@ -762,7 +810,7 @@ public V8Locker getLocker() { * * @return The unique build ID of the Native library. */ - public long getBuildID() { + public static long getBuildID() { return _getBuildID(); } @@ -854,7 +902,7 @@ protected void weakReferenceReleased(final long objectID) { if (v8Value != null) { v8WeakReferences.remove(objectID); try { - v8Value.release(); + 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, @@ -940,13 +988,13 @@ private void releaseArguments(final Object[] args, final boolean hasVarArgs) { Object[] varArgs = (Object[]) args[args.length - 1]; for (Object object : varArgs) { if (object instanceof V8Value) { - ((V8Value) object).release(); + ((V8Value) object).close(); } } } for (Object arg : args) { if (arg instanceof V8Value) { - ((V8Value) arg).release(); + ((V8Value) arg).close(); } } } @@ -1046,6 +1094,10 @@ protected long initNewV8Object(final long v8RuntimePtr) { return _initNewV8Object(v8RuntimePtr); } + protected long initEmptyContainer(final long v8RuntimePtr) { + return _initEmptyContainer(v8RuntimePtr); + } + protected void acquireLock(final long v8RuntimePtr) { _acquireLock(v8RuntimePtr); } @@ -1090,6 +1142,10 @@ 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); } @@ -1320,6 +1376,10 @@ 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); } @@ -1394,6 +1454,8 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho private native long _initNewV8Object(long v8RuntimePtr); + private native long _initEmptyContainer(long v8RuntimePtr); + private native void _acquireLock(long v8RuntimePtr); private native void _releaseLock(long v8RuntimePtr); @@ -1404,9 +1466,13 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho private native void _releaseRuntime(long v8RuntimePtr); - // HYBRID MODIFY: - //private native long _createIsolate(String globalAlias); - private native long _createIsolate(String globalAlias, String nativejsSnapshotSoName); + 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); @@ -1518,6 +1584,8 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho 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); @@ -1566,6 +1634,8 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho 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); @@ -1578,7 +1648,7 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho private native long _getGlobalObject(final long v8RuntimePtr); - private native long _getBuildID(); + private native static long _getBuildID(); private native static void _startNodeJS(final long v8RuntimePtr, final String fileName); @@ -1586,6 +1656,19 @@ protected void releaseMethodDescriptor(final long v8RuntimePtr, final long metho 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()) { diff --git a/src/main/java/com/eclipsesource/v8/V8Array.java b/src/main/java/com/eclipsesource/v8/V8Array.java index 807353b..3523261 100644 --- a/src/main/java/com/eclipsesource/v8/V8Array.java +++ b/src/main/java/com/eclipsesource/v8/V8Array.java @@ -633,11 +633,20 @@ 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() { } diff --git a/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java b/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java index bada577..4ecd48e 100644 --- a/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java +++ b/src/main/java/com/eclipsesource/v8/V8ArrayBuffer.java @@ -25,7 +25,7 @@ */ public class V8ArrayBuffer extends V8Value { - private ByteBuffer byteBuffer; + ByteBuffer byteBuffer; /** * Creates a new V8ArrayBuffer on a given V8Runtime with a @@ -41,17 +41,11 @@ public V8ArrayBuffer(final V8 v8, final int capacity) { byteBuffer.order(ByteOrder.nativeOrder()); } - /** - * Creates a new V8ArrayBuffer with the provided ByteBuffer as the backing store. - * The ByteBuffer must be allocated as a DirectBuffer. If the ByteBuffer is not - * a DirectBuffer an IllegalArgumentException will be thrown. - * - * @param v8 The runtime on which to create the ArrayBuffer - * @param byteBuffer The ByteBuffer to use as the backing store. The ByteBuffer must - * be allocated as a DirectBuffer. - */ - public V8ArrayBuffer(final V8 v8, final ByteBuffer byteBuffer) { + public V8ArrayBuffer(final V8 v8, ByteBuffer byteBuffer) { super(v8); + if (byteBuffer == null) { + byteBuffer = ByteBuffer.allocateDirect(0); + } if (!byteBuffer.isDirect()) { throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer"); } @@ -86,18 +80,393 @@ protected V8Value createTwin() { */ @Override public V8ArrayBuffer twin() { + v8.checkThread(); + checkReleased(); return (V8ArrayBuffer) super.twin(); } /** - * Returns the backing store used for this ArrayBuffer. + * Returns the buffers limit + * + * @return the buffers limit + */ + public int limit() { + v8.checkThread(); + checkReleased(); + return byteBuffer.limit(); + } + + /** + * Returns the buffers capacity + * + * @return the buffers capacity + */ + public final int capacity() { + v8.checkThread(); + checkReleased(); + return byteBuffer.capacity(); + } + + /** * - * @return The backing store used for this ArrayBuffer. + * @return */ - public ByteBuffer getBackingStore() { + 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; + return byteBuffer.asDoubleBuffer().limit(); } } diff --git a/src/main/java/com/eclipsesource/v8/V8Function.java b/src/main/java/com/eclipsesource/v8/V8Function.java index e8cdb1a..c9fba3c 100644 --- a/src/main/java/com/eclipsesource/v8/V8Function.java +++ b/src/main/java/com/eclipsesource/v8/V8Function.java @@ -83,6 +83,7 @@ public V8Function twin() { * * @return The result of JavaScript function. */ + @SuppressWarnings("resource") public Object call(V8Object receiver, final V8Array parameters) { v8.checkThread(); checkReleased(); diff --git a/src/main/java/com/eclipsesource/v8/V8Object.java b/src/main/java/com/eclipsesource/v8/V8Object.java index f64a027..640e2a1 100644 --- a/src/main/java/com/eclipsesource/v8/V8Object.java +++ b/src/main/java/com/eclipsesource/v8/V8Object.java @@ -399,15 +399,15 @@ public Object executeJSFunction(final String name, final Object... parameters) { } else if (object instanceof V8Value) { parameterArray.push((V8Value) object); } else if (object instanceof Integer) { - parameterArray.push((Integer) object); + parameterArray.push(object); } else if (object instanceof Double) { - parameterArray.push((Double) object); + parameterArray.push(object); } else if (object instanceof Long) { parameterArray.push(((Long) object).doubleValue()); } else if (object instanceof Float) { parameterArray.push(((Float) object).floatValue()); } else if (object instanceof Boolean) { - parameterArray.push((Boolean) object); + parameterArray.push(object); } else if (object instanceof String) { parameterArray.push((String) object); } else { @@ -416,7 +416,7 @@ public Object executeJSFunction(final String name, final Object... parameters) { } return executeFunction(name, parameterArray); } finally { - parameterArray.release(); + parameterArray.close(); } } @@ -683,10 +683,19 @@ 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() { } diff --git a/src/main/java/com/eclipsesource/v8/V8TypedArray.java b/src/main/java/com/eclipsesource/v8/V8TypedArray.java index ec36589..423f9a7 100644 --- a/src/main/java/com/eclipsesource/v8/V8TypedArray.java +++ b/src/main/java/com/eclipsesource/v8/V8TypedArray.java @@ -10,8 +10,6 @@ ******************************************************************************/ package com.eclipsesource.v8; -import java.nio.ByteBuffer; - /** * A representation of a JS TypedArray in Java. The typed array is simply a 'view' onto * a back buffer. @@ -37,6 +35,41 @@ 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. @@ -47,20 +80,6 @@ public V8ArrayBuffer getBuffer() { return (V8ArrayBuffer) get("buffer"); } - /** - * Returns the underlying ByteBuffer used to back this TypedArray. - * - * @return The ByteBuffer used as the backing store for this TypedArray - */ - public ByteBuffer getByteBuffer() { - V8ArrayBuffer buffer = getBuffer(); - try { - return buffer.getBackingStore(); - } finally { - buffer.release(); - } - } - @Override protected void initialize(final long runtimePtr, final Object data) { v8.checkThread(); @@ -136,7 +155,7 @@ private void checkSize(final V8ArrayData arrayData) { throw new IllegalStateException("RangeError: Invalid typed array length"); } int limit = (arrayData.size * getStructureSize(arrayData.type)) + arrayData.offset; - if (limit > arrayData.buffer.getBackingStore().limit()) { + if (limit > arrayData.buffer.limit()) { throw new IllegalStateException("RangeError: Invalid typed array length"); } } @@ -147,11 +166,6 @@ private void checkOffset(final V8ArrayData arrayData) { } } - @Override - protected V8Value createTwin() { - return new V8TypedArray(v8); - } - private static class V8ArrayData { private V8ArrayBuffer buffer; private int offset; diff --git a/src/main/java/com/eclipsesource/v8/V8Value.java b/src/main/java/com/eclipsesource/v8/V8Value.java index 187347c..0804bf9 100644 --- a/src/main/java/com/eclipsesource/v8/V8Value.java +++ b/src/main/java/com/eclipsesource/v8/V8Value.java @@ -12,16 +12,16 @@ /** * A base class for all V8 resources. V8 resources must - * be released. The rules for releasing resources is as + * be closed/released. The rules for releasing resources is as * follows: * - * 1. If you created it, you must release it, with one exception; + * 1. If you created it, you must close it, with one exception; * if the object is being passed pack via a return statement, * the system will release it for you. * * 2. If the system created it, you 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 release it. + * result of a method call, you must close it. */ abstract public class V8Value implements Releasable { @@ -143,6 +143,17 @@ public static String getStringRepresentation(final int 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. * @@ -184,7 +195,7 @@ public int getV8Type() { * will be updated. Twins are .equal and .strict equals, but * not == in Java. * - * Twins must be released separately since they have their own + * Twins must be closed separately since they have their own * native resources. * * @return A new Java object pointing at the same V8 Value @@ -203,13 +214,13 @@ public V8Value twin() { /** * Sets the V8Value as weak reference. A weak reference will eventually - * be released when no more references exist to this object. Once setWeak + * 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 released, so this should only be used if there is no + * the object will be closed, so this should only be used if there is no * other way to track object usage. * * @return The receiver. @@ -222,6 +233,24 @@ public V8Value setWeak() { 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. @@ -234,11 +263,12 @@ public boolean isWeak() { return v8.isWeak(v8.getV8RuntimePtr(), getHandle()); } - /** - * Releases the native resources associated with this V8Value. + /* + * (non-Javadoc) + * @see java.io.Closeable#close() */ @Override - public void release() { + public void close() { v8.checkThread(); if (!released) { try { @@ -250,6 +280,17 @@ public void release() { } } + /** + * 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. diff --git a/src/main/java/com/eclipsesource/v8/debug/DebugHandler.java b/src/main/java/com/eclipsesource/v8/debug/DebugHandler.java index 6346d40..ffb680d 100644 --- a/src/main/java/com/eclipsesource/v8/debug/DebugHandler.java +++ b/src/main/java/com/eclipsesource/v8/debug/DebugHandler.java @@ -105,7 +105,7 @@ public int setBreakpoint(final V8Function function) { try { return debugObject.executeIntegerFunction(SET_BREAK_POINT, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -124,7 +124,7 @@ public int setScriptBreakpoint(final String scriptID, final int lineNumber) { try { return debugObject.executeIntegerFunction(SET_SCRIPT_BREAK_POINT_BY_NAME, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -139,7 +139,7 @@ public void enableScriptBreakPoint(final int breakpointID) { try { debugObject.executeVoidFunction(ENABLE_SCRIPT_BREAK_POINT, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -154,7 +154,7 @@ public void disableScriptBreakPoint(final int breakpointID) { try { debugObject.executeVoidFunction(DISABLE_SCRIPT_BREAK_POINT, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -169,7 +169,7 @@ public void clearBreakPoint(final int breakpointID) { try { debugObject.executeVoidFunction(CLEAR_BREAK_POINT, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -190,7 +190,7 @@ public int getScriptBreakPointCount() { try { return breakPoints.length(); } finally { - breakPoints.release(); + breakPoints.close(); } } @@ -208,12 +208,12 @@ public int[] getScriptBreakPointIDs() { try { result[i] = breakPoint.executeIntegerFunction(NUMBER, null); } finally { - breakPoint.release(); + breakPoint.close(); } } return result; } finally { - breakPoints.release(); + breakPoints.close(); } } @@ -232,9 +232,9 @@ public ScriptBreakPoint getScriptBreakPoint(final int breakPointID) { scriptBreakPoint = debugObject.executeObjectFunction(FIND_SCRIPT_BREAK_POINT, parameters); return new ScriptBreakPoint(scriptBreakPoint); } finally { - parameters.release(); + parameters.close(); if (scriptBreakPoint != null) { - scriptBreakPoint.release(); + scriptBreakPoint.close(); } } } @@ -252,13 +252,23 @@ public void changeBreakPointCondition(final int breakpointID, final String condi try { debugObject.executeVoidFunction(CHANGE_BREAK_POINT_CONDITION, parameters); } finally { - parameters.release(); + parameters.close(); } } + /* + * (non-Javadoc) + * @see java.io.Closeable#close() + */ + @Override + public void close() { + debugObject.close(); + } + @Override + @Deprecated public void release() { - debugObject.release(); + close(); } private void setupDebugObject(final V8 runtime) { @@ -266,7 +276,7 @@ private void setupDebugObject(final V8 runtime) { try { debugObject = outerDebug.getObject(V8_DEBUG_OBJECT); } finally { - outerDebug.release(); + outerDebug.close(); } } @@ -277,14 +287,15 @@ private void setupBreakpointHandler() { V8Array parameters = null; try { debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER); - parameters = new V8Array(runtime).push(debugHandler); + parameters = new V8Array(runtime); + parameters.push(debugHandler); debugObject.executeFunction(SET_LISTENER, parameters); } finally { if ((debugHandler != null) && !debugHandler.isReleased()) { - debugHandler.release(); + debugHandler.close(); } if ((parameters != null) && !parameters.isReleased()) { - parameters.release(); + parameters.close(); } } } diff --git a/src/main/java/com/eclipsesource/v8/debug/EventData.java b/src/main/java/com/eclipsesource/v8/debug/EventData.java index e31342e..8b58a9c 100644 --- a/src/main/java/com/eclipsesource/v8/debug/EventData.java +++ b/src/main/java/com/eclipsesource/v8/debug/EventData.java @@ -25,10 +25,16 @@ public class EventData implements Releasable { } @Override - public void release() { + public void close() { if (!v8Object.isReleased()) { - v8Object.release(); + v8Object.close(); } } + @Override + @Deprecated + public void release() { + close(); + } + } diff --git a/src/main/java/com/eclipsesource/v8/debug/ExecutionState.java b/src/main/java/com/eclipsesource/v8/debug/ExecutionState.java index 77dad6f..43adb1b 100644 --- a/src/main/java/com/eclipsesource/v8/debug/ExecutionState.java +++ b/src/main/java/com/eclipsesource/v8/debug/ExecutionState.java @@ -58,7 +58,7 @@ public void prepareStep(final StepAction action) { try { v8Object.executeVoidFunction(PREPARE_STEP, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -76,19 +76,25 @@ public Frame getFrame(final int index) { frame = v8Object.executeObjectFunction(FRAME, parameters); return new Frame(frame); } finally { - parameters.release(); + parameters.close(); if (frame != null) { - frame.release(); + frame.close(); } } } @Override - public void release() { + public void close() { if ((v8Object != null) && !v8Object.isReleased()) { - v8Object.release(); + v8Object.close(); v8Object = null; } } + @Override + @Deprecated + public void release() { + close(); + } + } \ No newline at end of file diff --git a/src/main/java/com/eclipsesource/v8/debug/ScriptBreakPoint.java b/src/main/java/com/eclipsesource/v8/debug/ScriptBreakPoint.java index 850c14b..d91ccc9 100644 --- a/src/main/java/com/eclipsesource/v8/debug/ScriptBreakPoint.java +++ b/src/main/java/com/eclipsesource/v8/debug/ScriptBreakPoint.java @@ -61,7 +61,7 @@ public void setCondition(final String condition) { try { v8Object.executeVoidFunction(SET_CONDITION, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -80,10 +80,15 @@ public String getCondition() { } @Override - public void release() { + public void close() { if ((v8Object != null) && !v8Object.isReleased()) { - v8Object.release(); + v8Object.close(); v8Object = null; } } + + @Override + public void release() { + close(); + } } diff --git a/src/main/java/com/eclipsesource/v8/debug/V8DebugServer.java b/src/main/java/com/eclipsesource/v8/debug/V8DebugServer.java index 8acbd44..f0e957d 100644 --- a/src/main/java/com/eclipsesource/v8/debug/V8DebugServer.java +++ b/src/main/java/com/eclipsesource/v8/debug/V8DebugServer.java @@ -141,7 +141,7 @@ public V8DebugServer(final V8 runtime, final int port, final boolean waitForConn try { debugObject = debugScope.getObject(V8_DEBUG_OBJECT); } finally { - debugScope.release(); + debugScope.close(); } runtime.executeVoidScript("(function() {\n" @@ -236,15 +236,15 @@ public void stop() { //release resources if (runningStateDcp != null) { - runningStateDcp.release(); + runningStateDcp.close(); runningStateDcp = null; } if (debugObject != null) { - debugObject.release(); + debugObject.close(); debugObject = null; } if (stoppedStateDcp != null) { - stoppedStateDcp.release(); + stoppedStateDcp.close(); stoppedStateDcp = null; } }; @@ -329,6 +329,7 @@ private void processRequest(final String message) throws IOException { V8Array params = new V8Array(runtime); params.push(message); + @SuppressWarnings("resource") V8Object dcp = stoppedStateDcp != null ? stoppedStateDcp : runningStateDcp; Object result = dcp.executeFunction("processDebugJSONRequest", params); @@ -356,14 +357,15 @@ private void setupEventHandler() { V8Array parameters = null; try { debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER); - parameters = new V8Array(runtime).push(debugHandler); + parameters = new V8Array(runtime); + parameters.push(debugHandler); debugObject.executeFunction(SET_LISTENER, parameters); } finally { if ((debugHandler != null) && !debugHandler.isReleased()) { - debugHandler.release(); + debugHandler.close(); } if ((parameters != null) && !parameters.isReleased()) { - parameters.release(); + parameters.close(); } } } @@ -375,7 +377,7 @@ private void enterBreakLoop(final V8Object execState, final V8Object eventData) params.push(false); stoppedStateDcp = execState.executeObjectFunction("debugCommandProcessor", params); } finally { - params.release(); + params.close(); } //send event to debugger @@ -394,10 +396,10 @@ private void enterBreakLoop(final V8Object execState, final V8Object eventData) } sendJson(json); } finally { - params.release(); - breakpointsHit.release(); + params.close(); + breakpointsHit.close(); if (event != null) { - event.release(); + event.close(); } } @@ -410,7 +412,7 @@ private void enterBreakLoop(final V8Object execState, final V8Object eventData) } } } finally { - stoppedStateDcp.release(); + stoppedStateDcp.close(); stoppedStateDcp = null; } } @@ -437,10 +439,10 @@ private void sendCompileEvent(final V8Object eventData) throws IOException { sendJson(json); } } finally { - params.release(); - script.release(); + params.close(); + script.close(); if (event != null) { - event.release(); + event.close(); } } } diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/Frame.java b/src/main/java/com/eclipsesource/v8/debug/mirror/Frame.java index 99ab845..f06c838 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/Frame.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/Frame.java @@ -63,7 +63,7 @@ public SourceLocation getSourceLocation() { V8Object scriptObject = (V8Object) sourceLocation.get(SCRIPT); if (scriptObject != null) { scriptName = scriptObject.getString(NAME); - scriptObject.release(); + scriptObject.close(); } if ((scriptName == null) && (functionScriptName != null)) { scriptName = functionScriptName; @@ -76,8 +76,8 @@ public SourceLocation getSourceLocation() { sourceLocation.getInteger(COLUMN), sourceLocation.getString(SOURCE_TEXT)); } finally { - function.release(); - sourceLocation.release(); + function.close(); + sourceLocation.close(); } } @@ -102,7 +102,7 @@ public String getArgumentName(final int index) { try { return v8Object.executeStringFunction(ARGUMENT_NAME, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -123,9 +123,9 @@ public ValueMirror getArgumentValue(final int index) { } return new ValueMirror(result); } finally { - parameters.release(); + parameters.close(); if (result != null) { - result.release(); + result.close(); } } } @@ -147,9 +147,9 @@ public ValueMirror getLocalValue(final int index) { } return createMirror(result); } finally { - parameters.release(); + parameters.close(); if (result != null) { - result.release(); + result.close(); } } } @@ -175,7 +175,7 @@ public String getLocalName(final int index) { try { return v8Object.executeStringFunction(LOCAL_NAME, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -193,9 +193,9 @@ public Scope getScope(final int index) { scope = v8Object.executeObjectFunction(SCOPE, parameters); return new Scope(scope); } finally { - parameters.release(); + parameters.close(); if (scope != null) { - scope.release(); + scope.close(); } } } @@ -212,7 +212,7 @@ public FunctionMirror getFunction() { return new FunctionMirror(function); } finally { if (function != null) { - function.release(); + function.close(); } } } diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/FunctionMirror.java b/src/main/java/com/eclipsesource/v8/debug/mirror/FunctionMirror.java index 57bb434..fb5fea4 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/FunctionMirror.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/FunctionMirror.java @@ -44,7 +44,7 @@ public String getScriptName() { try { return script.executeStringFunction(NAME, null); } finally { - script.release(); + script.close(); } } diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/Mirror.java b/src/main/java/com/eclipsesource/v8/debug/mirror/Mirror.java index 9b8eaa3..3dc5e02 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/Mirror.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/Mirror.java @@ -156,14 +156,28 @@ public boolean isProperty() { return false; } + /* + * (non-Javadoc) + * @see java.io.Closeable#close() + */ @Override - public void release() { + public void close() { if ((v8Object != null) && !v8Object.isReleased()) { - v8Object.release(); + v8Object.close(); v8Object = null; } } + /* + * (non-Javadoc) + * @see com.eclipsesource.v8.Releasable#release() + */ + @Override + @Deprecated + public void release() { + close(); + } + protected static boolean isValue(final V8Object mirror) { try { return mirror.executeBooleanFunction(IS_VALUE, null); diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/ObjectMirror.java b/src/main/java/com/eclipsesource/v8/debug/mirror/ObjectMirror.java index b9a5e8b..11131d6 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/ObjectMirror.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/ObjectMirror.java @@ -64,9 +64,9 @@ public String[] getPropertyNames(final PropertyKind kind, final int limit) { } return result; } finally { - parameters.release(); + parameters.close(); if (propertyNames != null) { - propertyNames.release(); + propertyNames.close(); } } } @@ -87,9 +87,9 @@ public PropertiesArray getProperties(final PropertyKind kind, final int limit) { result = v8Object.executeArrayFunction(PROPERTIES, parameters); return new PropertiesArray(result); } finally { - parameters.release(); + parameters.close(); if ((result != null) && !result.isReleased()) { - result.release(); + result.close(); result = null; } } diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/PropertiesArray.java b/src/main/java/com/eclipsesource/v8/debug/mirror/PropertiesArray.java index c247e9e..e9cea1e 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/PropertiesArray.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/PropertiesArray.java @@ -36,17 +36,31 @@ public PropertyMirror getProperty(final int index) { try { return new PropertyMirror(result); } finally { - result.release(); + result.close(); } } + /* + * (non-Javadoc) + * @see java.io.Closeable#close() + */ @Override - public void release() { + public void close() { if (!v8Array.isReleased()) { - v8Array.release(); + v8Array.close(); } } + /* + * (non-Javadoc) + * @see com.eclipsesource.v8.Releasable#release() + */ + @Override + @Deprecated + public void release() { + close(); + } + /** * Returns the number of properties contained in this array. * diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/PropertyMirror.java b/src/main/java/com/eclipsesource/v8/debug/mirror/PropertyMirror.java index be94c76..235f657 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/PropertyMirror.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/PropertyMirror.java @@ -40,7 +40,7 @@ public Mirror getValue() { try { return createMirror(mirror); } finally { - mirror.release(); + mirror.close(); } } diff --git a/src/main/java/com/eclipsesource/v8/debug/mirror/Scope.java b/src/main/java/com/eclipsesource/v8/debug/mirror/Scope.java index 8203206..9c3b0d2 100644 --- a/src/main/java/com/eclipsesource/v8/debug/mirror/Scope.java +++ b/src/main/java/com/eclipsesource/v8/debug/mirror/Scope.java @@ -63,7 +63,7 @@ public void setVariableValue(final String name, final int value) { try { v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -80,7 +80,7 @@ public void setVariableValue(final String name, final V8Value value) { try { v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -97,7 +97,7 @@ public void setVariableValue(final String name, final boolean value) { try { v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -114,7 +114,7 @@ public void setVariableValue(final String name, final String value) { try { v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -131,7 +131,7 @@ public void setVariableValue(final String name, final double value) { try { v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); } finally { - parameters.release(); + parameters.close(); } } @@ -147,7 +147,7 @@ public ObjectMirror getScopeObject() { return (ObjectMirror) createMirror(mirror); } finally { if ( mirror != null ) { - mirror.release(); + mirror.close(); } } diff --git a/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java b/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java new file mode 100644 index 0000000..de1d9b5 --- /dev/null +++ b/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java @@ -0,0 +1,7 @@ +package com.eclipsesource.v8.inspector; + +public interface DebuggerConnectionListener { + public void onDebuggerConnected(); + + public void onDebuggerDisconnected(); +} diff --git a/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java b/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java new file mode 100644 index 0000000..2034fcd --- /dev/null +++ b/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java @@ -0,0 +1,67 @@ +package com.eclipsesource.v8.inspector; + +import java.util.ArrayList; +import java.util.List; + +import com.eclipsesource.v8.V8; +import com.eclipsesource.v8.V8Object; + +public class V8Inspector { + + private V8 runtime; + private long inspectorPtr = 0; + private boolean waitingForConnection = true; + private List debuggerConnectionListeners; + + protected V8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate, final String contextName) { + this.runtime = runtime; + inspectorPtr = runtime.createInspector(inspectorDelegate, contextName); + debuggerConnectionListeners = new ArrayList(); + } + + public static V8Inspector createV8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate, final String contextName) { + return new V8Inspector(runtime, inspectorDelegate, contextName); + } + + public static V8Inspector createV8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate) { + return new V8Inspector(runtime, inspectorDelegate, null); + } + + public void dispatchProtocolMessage(final String protocolMessage) { + try { + runtime.dispatchProtocolMessage(inspectorPtr, protocolMessage); + if (waitingForConnection) { + verifyDebuggerConnection(protocolMessage); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void addDebuggerConnectionListener(final DebuggerConnectionListener listener) { + debuggerConnectionListeners.add(listener); + } + + public void removeDebuggerConnectionListener(final DebuggerConnectionListener listener) { + debuggerConnectionListeners.remove(listener); + } + + private void verifyDebuggerConnection(final String protocolMessage) { + V8Object json = null; + try { + json = runtime.executeObjectScript("JSON.parse(JSON.stringify(" + protocolMessage + "))"); + if (json.getString("method").equals("Runtime.runIfWaitingForDebugger")) { + waitingForConnection = false; + runtime.schedulePauseOnNextStatement(inspectorPtr, ""); + for (DebuggerConnectionListener listener : debuggerConnectionListeners) { + listener.onDebuggerConnected(); + } + } + } finally { + if (json != null) { + json.close(); + } + } + } + +} diff --git a/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java b/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java new file mode 100644 index 0000000..c799dcc --- /dev/null +++ b/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java @@ -0,0 +1,7 @@ +package com.eclipsesource.v8.inspector; + +public interface V8InspectorDelegate { + public void onResponse(String message); + + public void waitFrontendMessageOnPause(); +} diff --git a/src/main/java/com/eclipsesource/v8/utils/ArrayBuffer.java b/src/main/java/com/eclipsesource/v8/utils/ArrayBuffer.java new file mode 100644 index 0000000..d1a39b8 --- /dev/null +++ b/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/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java b/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java index e3b75e4..a1b9d60 100644 --- a/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java +++ b/src/main/java/com/eclipsesource/v8/utils/ConcurrentV8.java @@ -85,7 +85,7 @@ public void release() { @Override public void run(final V8 v8) { if ((v8 != null) && !v8.isReleased()) { - v8.release(); + v8.close(); } } }); diff --git a/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java b/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java index ddb4f88..7f236ae 100644 --- a/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java +++ b/src/main/java/com/eclipsesource/v8/utils/MemoryManager.java @@ -98,7 +98,7 @@ public void release() { releasing = true; try { for (V8Value reference : references) { - reference.release(); + reference.close(); } v8.removeReferenceHandler(memoryManagerReferenceHandler); references.clear(); diff --git a/src/main/java/com/eclipsesource/v8/utils/TypedArray.java b/src/main/java/com/eclipsesource/v8/utils/TypedArray.java new file mode 100644 index 0000000..1c1616a --- /dev/null +++ b/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/src/main/java/com/eclipsesource/v8/utils/V8Executor.java b/src/main/java/com/eclipsesource/v8/utils/V8Executor.java index 50f8c34..881a229 100644 --- a/src/main/java/com/eclipsesource/v8/utils/V8Executor.java +++ b/src/main/java/com/eclipsesource/v8/utils/V8Executor.java @@ -125,9 +125,6 @@ public void run() { if (scriptResult instanceof Releasable) { ((Releasable) scriptResult).release(); } - if (scriptResult instanceof Releasable) { - ((Releasable) scriptResult).release(); - } } while (!forceTerminating && longRunning) { synchronized (this) { @@ -149,8 +146,8 @@ public void run() { parameters.push(strings); runtime.executeVoidFunction(messageHandler, parameters); } finally { - strings.release(); - parameters.release(); + strings.close(); + parameters.close(); } } } @@ -159,7 +156,7 @@ public void run() { } finally { synchronized (this) { if (runtime.getLocker().hasLock()) { - runtime.release(); + runtime.close(); runtime = null; } terminated = true; diff --git a/src/main/java/com/eclipsesource/v8/utils/V8Map.java b/src/main/java/com/eclipsesource/v8/utils/V8Map.java index 08343fb..fa8d58c 100644 --- a/src/main/java/com/eclipsesource/v8/utils/V8Map.java +++ b/src/main/java/com/eclipsesource/v8/utils/V8Map.java @@ -40,14 +40,24 @@ public V8Map() { 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() { - this.clear(); + close(); } /* @@ -116,7 +126,7 @@ public V remove(final Object key) { V result = map.remove(key); V8Value twin = twinMap.remove(key); if (twin != null) { - twin.release(); + twin.close(); } return result; } @@ -127,7 +137,7 @@ public V remove(final Object key) { */ @Override public void putAll(final Map m) { - for (Entry entry : m.entrySet()) { + for (java.util.Map.Entry entry : m.entrySet()) { this.put(entry.getKey(), entry.getValue()); } } @@ -140,7 +150,7 @@ public void putAll(final Map m) { public void clear() { map.clear(); for (V8Value V8Value : twinMap.keySet()) { - V8Value.release(); + V8Value.close(); } twinMap.clear(); } @@ -168,7 +178,7 @@ public Collection values() { * @see java.util.Map#entrySet() */ @Override - public Set> entrySet() { + public Set> entrySet() { return map.entrySet(); } diff --git a/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java b/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java index 736e3a4..b433565 100644 --- a/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java +++ b/src/main/java/com/eclipsesource/v8/utils/V8ObjectUtils.java @@ -10,7 +10,6 @@ ******************************************************************************/ package com.eclipsesource.v8.utils; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; @@ -25,17 +24,6 @@ import com.eclipsesource.v8.V8Object; import com.eclipsesource.v8.V8TypedArray; import com.eclipsesource.v8.V8Value; -import com.eclipsesource.v8.utils.typedarrays.ArrayBuffer; -import com.eclipsesource.v8.utils.typedarrays.Float32Array; -import com.eclipsesource.v8.utils.typedarrays.Float64Array; -import com.eclipsesource.v8.utils.typedarrays.Int16Array; -import com.eclipsesource.v8.utils.typedarrays.Int32Array; -import com.eclipsesource.v8.utils.typedarrays.Int8Array; -import com.eclipsesource.v8.utils.typedarrays.TypedArray; -import com.eclipsesource.v8.utils.typedarrays.UInt16Array; -import com.eclipsesource.v8.utils.typedarrays.UInt32Array; -import com.eclipsesource.v8.utils.typedarrays.UInt8Array; -import com.eclipsesource.v8.utils.typedarrays.UInt8ClampedArray; /** * A set of static helper methods to convert V8Objects / V8Arrays to @@ -92,7 +80,7 @@ public static Object getValue(final Object v8Object, final TypeAdapter adapter) return v8Object; } } finally { - cache.release(); + cache.close(); } } @@ -124,7 +112,7 @@ public static Object getValue(final Object v8Object, final TypeAdapter adapter) try { return toMap(object, cache, adapter); } finally { - cache.release(); + cache.close(); } } @@ -156,7 +144,7 @@ public static List toList(final V8Array array, final TypeAdapter try { return toList(array, cache, adapter); } finally { - cache.release(); + cache.close(); } } @@ -258,7 +246,7 @@ public static V8Object toV8Object(final V8 v8, final Map list) return toV8Array(v8, list, cache).twin(); } finally { for (V8Value v8Object : cache.values()) { - v8Object.release(); + v8Object.close(); } } } @@ -310,7 +298,7 @@ public static Object getV8Result(final V8 v8, final Object value) { return result; } finally { for (V8Value v8Object : cache.values()) { - v8Object.release(); + v8Object.close(); } } } @@ -331,7 +319,7 @@ public static void pushValue(final V8 v8, final V8Array array, final Object valu pushValue(v8, array, value, cache); } finally { for (V8Value v8Object : cache.values()) { - v8Object.release(); + v8Object.close(); } } } @@ -355,12 +343,16 @@ public static Object getValue(final V8Array array, final int index) { try { object = array.get(index); type = array.getType(index); - return getValue(object, type, cache, DEFAULT_TYPE_ADAPTER); + 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.release(); + cache.close(); } } @@ -385,12 +377,16 @@ public static Object getValue(final V8Array array, final int index, final TypeAd try { object = array.get(index); type = array.getType(index); - return getValue(object, type, cache, adapter); + 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.release(); + cache.close(); } } @@ -431,12 +427,16 @@ public static Object getValue(final V8Object v8Object, final String key, final T try { object = v8Object.get(key); type = v8Object.getType(key); - return getValue(object, type, cache, adapter); + 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.release(); + cache.close(); } } @@ -499,6 +499,24 @@ private static List toList(final V8Array array, final V8Map 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); @@ -510,7 +528,7 @@ private static V8Object toV8Object(final V8 v8, final Map list, pushValue(v8, result, value, cache); } } catch (IllegalStateException e) { - result.release(); + result.close(); throw e; } return result; } - private static V8ArrayBuffer toV8ArrayBuffer(final V8 v8, final ArrayBuffer arrayBuffer, final Map cache) { - if (cache.containsKey(arrayBuffer)) { - return (V8ArrayBuffer) cache.get(arrayBuffer); - } - V8ArrayBuffer result = new V8ArrayBuffer(v8, arrayBuffer.getByteBuffer()); - cache.put(arrayBuffer, result); - return result; - } - - private static V8TypedArray toV8TypedArray(final V8 v8, final TypedArray typedArray, final Map cache) { - if (cache.containsKey(typedArray)) { - return (V8TypedArray) cache.get(typedArray); - } - V8ArrayBuffer arrayBuffer = new V8ArrayBuffer(v8, typedArray.getByteBuffer()); - try { - V8TypedArray result = new V8TypedArray(v8, arrayBuffer, typedArray.getType(), 0, typedArray.length()); - cache.put(typedArray, result); - return result; - } finally { - arrayBuffer.release(); - } - } - @SuppressWarnings("unchecked") private static Object getV8Result(final V8 v8, final Object value, final Map cache) { if (cache.containsKey(value)) { @@ -574,7 +569,7 @@ private static Object getV8Result(final V8 v8, final Object value, final Map cache) { if (value == null) { result.pushUndefined(); @@ -590,14 +585,14 @@ private static void pushValue(final V8 v8, final V8Array result, final Object va result.push((String) value); } else if (value instanceof Boolean) { result.push(value); - } else if (value instanceof V8Object) { - result.push((V8Object) 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); @@ -609,7 +604,7 @@ private static void pushValue(final V8 v8, final V8Array result, final Object va } } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes", "resource" }) private static void setValue(final V8 v8, final V8Object result, final String key, final Object value, final Map cache) { if (value == null) { result.addUndefined(key); @@ -625,14 +620,14 @@ private static void setValue(final V8 v8, final V8Object result, final String ke result.add(key, (String) value); } else if (value instanceof Boolean) { result.add(key, (Boolean) value); - } else if (value instanceof V8Object) { - result.add(key, (V8Object) value); } else if (value instanceof TypedArray) { - V8TypedArray typedArray = toV8TypedArray(v8, (TypedArray) value, cache); - result.add(key, typedArray); + V8TypedArray v8TypedArray = toV8TypedArray(v8, (TypedArray) value, cache); + result.add(key, v8TypedArray); } else if (value instanceof ArrayBuffer) { V8ArrayBuffer v8ArrayBuffer = toV8ArrayBuffer(v8, (ArrayBuffer) value, cache); result.add(key, v8ArrayBuffer); + } else if (value instanceof V8Value) { + result.add(key, (V8Value) value); } else if (value instanceof Map) { V8Object object = toV8Object(v8, (Map) value, cache); result.add(key, object); @@ -658,18 +653,9 @@ private static Object getValue(final Object value, final int valueType, final V8 case V8Value.V8_FUNCTION: return IGNORE; case V8Value.V8_ARRAY_BUFFER: - //HYBRID MODIFY BEGIN: - // return new ArrayBuffer(((V8ArrayBuffer) value).getBackingStore()); - { - if (value == null) { - return new ArrayBuffer(0); - } - return new ArrayBuffer(((V8ArrayBuffer) value).getBackingStore()); - - } - // HYBRID END + return new ArrayBuffer((V8ArrayBuffer) value); case V8Value.V8_TYPED_ARRAY: - return toTypedArray((V8Array) value); + return new TypedArray((V8TypedArray) value); case V8Value.V8_ARRAY: return toList((V8Array) value, cache, adapter); case V8Value.V8_OBJECT: @@ -683,33 +669,6 @@ private static Object getValue(final Object value, final int valueType, final V8 } } - private static Object toTypedArray(final V8Array typedArray) { - int arrayType = typedArray.getType(); - ByteBuffer buffer = ((V8TypedArray) typedArray).getByteBuffer(); - switch (arrayType) { - case V8Value.INT_8_ARRAY: - return new Int8Array(buffer); - case V8Value.UNSIGNED_INT_8_ARRAY: - return new UInt8Array(buffer); - case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY: - return new UInt8ClampedArray(buffer); - case V8Value.INT_16_ARRAY: - return new Int16Array(buffer); - case V8Value.UNSIGNED_INT_16_ARRAY: - return new UInt16Array(buffer); - case V8Value.INT_32_ARRAY: - return new Int32Array(buffer); - case V8Value.UNSIGNED_INT_32_ARRAY: - return new UInt32Array(buffer); - case V8Value.FLOAT_32_ARRAY: - return new Float32Array(buffer); - case V8Value.FLOAT_64_ARRAY: - return new Float64Array(buffer); - default: - throw new IllegalStateException("Known Typed Array type: " + V8Value.getStringRepresentation(arrayType)); - } - } - private V8ObjectUtils() { } diff --git a/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java b/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java index a5d159d..db71881 100644 --- a/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java +++ b/src/main/java/com/eclipsesource/v8/utils/V8PropertyMap.java @@ -166,7 +166,7 @@ public Collection values() { */ @Override public Set> entrySet() { - HashSet> result = new HashSet>(map.entrySet()); + HashSet> result = new HashSet>(map.entrySet()); for (String nullKey : nulls) { result.add(new SimpleEntry(nullKey, null)); } diff --git a/src/main/java/com/eclipsesource/v8/utils/V8Thread.java b/src/main/java/com/eclipsesource/v8/utils/V8Thread.java index 5f0096f..0233ffb 100644 --- a/src/main/java/com/eclipsesource/v8/utils/V8Thread.java +++ b/src/main/java/com/eclipsesource/v8/utils/V8Thread.java @@ -47,7 +47,7 @@ public void run() { } finally { synchronized (this) { if (runtime.getLocker().hasLock()) { - runtime.release(); + runtime.close(); runtime = null; } } diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java deleted file mode 100644 index b9d0dc7..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/ArrayBuffer.java +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -/** - * A wrapper class for java.nio.ByteBuffer. This class provides some convenience methods - * for working with the ByteBuffer. Furthermore, this class can be converted to a - * V8ByteBuffer using V8ObjectUtils. - */ -public class ArrayBuffer { - - private ByteBuffer byteBuffer; - - /** - * Create a new ArrayBuffer with an initial capacity. - * - * @param capacity The capacity of this ByteBuffer. - */ - public ArrayBuffer(final int capacity) { - byteBuffer = ByteBuffer.allocateDirect(capacity); - } - - /** - * Create a new ArrayBuffer from a byte array. The array buffer will be allocated with the same - * size as the byte array, and the contents of the byte array will be copied to the ArrayBuffer. - * - * @param src The byte array from which the ArrayBuffer will be initialized. - */ - public ArrayBuffer(final byte[] src) { - byteBuffer = ByteBuffer.allocateDirect(src.length); - byteBuffer.put(src, 0, src.length); - } - - /** - * Create a new ArrayBuffer with the given ByteBuffer as the backing store. The ByteBuffer must - * be created as a DirectBuffer. - * - * @param byteBuffer The ByteBuffer to back this ArrayBuffer. - */ - public ArrayBuffer(final ByteBuffer byteBuffer) { - this.byteBuffer = validateByteBuffer(byteBuffer); - } - - private ByteBuffer validateByteBuffer(final ByteBuffer byteBuffer) { - if (!byteBuffer.isDirect()) { - throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer"); - } - return byteBuffer; - } - - /** - * Returns the ByteBuffer backing this ArrayBuffer. - * - * @return The ByteBuffer backing this ArrayBuffer. - */ - public ByteBuffer getByteBuffer() { - return byteBuffer; - } - - /** - * Returns the byte at a given index. - * - * @param index The index at which to return the byte. - * @return The byte at the given index. - */ - public byte getByte(final int index) { - return byteBuffer.get(index); - } - - /** - * Returns the byte at a given index as an unsigned integer. - * - * @param index The index at which to return the byte. - * @return The unsigned byte at the given index. - */ - public short getUnsignedByte(final int index) { - return (short) (0xFF & byteBuffer.get(index)); - } - - /** - * Puts a byte into the ByteBuffer at the given index. - * - * @param index The index at which to put the byte. - * @param value The value to put at the index. - */ - public void put(final int index, final byte value) { - byteBuffer.put(index, value); - } - - /** - * Returns this ArrayBuffers limit. - * - * @return This ArrayBuffers limit. - */ - public int limit() { - return byteBuffer.limit(); - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "[object ArrayBuffer]"; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float32Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float32Array.java deleted file mode 100644 index a5ab991..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float32Array.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Float32Array typed array represents an array of 32-bit floating - * point numbers. - */ -public class Float32Array extends TypedArray { - - /** - * Creates a Float32Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public Float32Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a Float32Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public Float32Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the floating point (Float32) value at a given index. - * - * @param index The index at which to return the value. - * @return The Float32 value at the given index. - */ - public float get(final int index) { - return buffer.asFloatBuffer().get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.asFloatBuffer().limit(); - } - - /** - * Puts a Float32 value at a particular index. - * - * @param index The index at which to place the value. - * @param value The Float32 value to place into buffer. - */ - public void put(final int index, final float value) { - buffer.asFloatBuffer().put(index, value); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.FLOAT_32_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float64Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float64Array.java deleted file mode 100644 index af7c670..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Float64Array.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Float64Array typed array represents an array of 64-bit floating - * point numbers. - */ -public class Float64Array extends TypedArray { - - /** - * Creates a Float64Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public Float64Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a Float64Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public Float64Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the floating point (Float64) value at a given index. - * - * @param index The index at which to return the value. - * @return The Double (Float64) value at the given index. - */ - public double get(final int index) { - return buffer.asDoubleBuffer().get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.asDoubleBuffer().limit(); - } - - /** - * Puts a Double (Float64) value at a particular index. - * - * @param index The index at which to place the value. - * @param value The Double to put into the buffer. - */ - public void put(final int index, final double value) { - buffer.asDoubleBuffer().put(index, value); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.FLOAT_64_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int16Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int16Array.java deleted file mode 100644 index ae365be..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int16Array.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Int16Array typed array represents an array of twos-complement - * 16-bit signed integers in the platform byte order. - */ -public class Int16Array extends TypedArray { - - /** - * Creates an Int16Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public Int16Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a Int16Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public Int16Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 16-bit signed integer at the given index - * - * @param index The index at which to return the value. - * @return The 16-bit integer at the index. - */ - public short get(final int index) { - return buffer.asShortBuffer().get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.asShortBuffer().limit(); - } - - /** - * Puts a 16-bit integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 16-bit integer to put into buffer. - */ - public void put(final int index, final short value) { - buffer.asShortBuffer().put(index, value); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.INT_16_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int32Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int32Array.java deleted file mode 100644 index 4e69e73..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int32Array.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Int32Array typed array represents an array of twos-complement 32-bit signed - * integers in the platform byte order. - */ -public class Int32Array extends TypedArray { - - /** - * Creates an Int32Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public Int32Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a Int32Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public Int32Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 32-bit signed integer at the given index. - * - * @param index The index at which to return the value. - * @return The 32-bit integer at the index. - */ - public int get(final int index) { - return buffer.asIntBuffer().get(index); - } - - @Override - public int length() { - return buffer.asIntBuffer().limit(); - } - - /** - * Puts a 32-bit integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 32-bit integer to put into buffer. - */ - public void put(final int index, final int value) { - buffer.asIntBuffer().put(index, value); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.INT_32_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int8Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int8Array.java deleted file mode 100644 index f75b61f..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/Int8Array.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Int8Array typed array represents an array of twos-complement - * 8-bit signed integers. - */ -public class Int8Array extends TypedArray { - - /** - * Creates an Int8Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public Int8Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a Int8Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public Int8Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 8-bit signed integer at the given index. - * - * @param index The index at which to return the value. - * @return The 8-bit integer at the index. - */ - public byte get(final int index) { - return buffer.get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.limit(); - } - - /** - * Puts an 8-bit integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 8-bit integer to put into buffer. - */ - public void put(final int index, final byte value) { - buffer.put(index, value); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.INT_8_ARRAY; - } -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/TypedArray.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/TypedArray.java deleted file mode 100644 index 567b877..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/TypedArray.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8TypedArray; - -/** - * An abstract class that represents TypedArrays - */ -public abstract class TypedArray { - - protected ByteBuffer buffer; - - protected TypedArray(final ByteBuffer buffer) { - if (!buffer.isDirect()) { - throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer"); - } - if ((buffer.limit() % V8TypedArray.getStructureSize(getType())) != 0) { - throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer"); - } - this.buffer = buffer; - } - - /** - * Return the underlying ByteBuffer. - * - * @return The underlying ByteBuffer behind this view - */ - public ByteBuffer getByteBuffer() { - return buffer; - } - - /** - * Return the size of this view. The size of the view is determined by the size - * of the buffer, and the size of the data projected onto it. For example, for a - * buffer size of 8, and a view representing 16bit integers, the size would be 4. - * - * @return The size of this view - */ - public abstract int length(); - - /** - * Returns the 'Type' of this TypedArray using one of the constants defined in V8Value. - * - * @return The 'Type' of this typed array. - */ - public abstract int getType(); -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java deleted file mode 100644 index cd62d2c..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt16Array.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Uint16Array typed array represents an array of 16-bit unsigned - * integers in the platform byte order. - */ -public class UInt16Array extends TypedArray { - - /** - * Creates an UInt16Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public UInt16Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a UInt16Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public UInt16Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 16-bit unsigned integer at the given index. - * - * @param index The index at which to return the value. - * @return The 16-bit unsigned integer at the index. - */ - public int get(final int index) { - return 0xFFFF & buffer.asShortBuffer().get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.asShortBuffer().limit(); - } - - /** - * Puts a 16-bit unsigned integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 16-bit unsigned integer to put into buffer. - */ - public void put(final int index, final int value) { - buffer.asShortBuffer().put(index, (short) (0x0000FFFF & value)); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.UNSIGNED_INT_16_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java deleted file mode 100644 index fd307e2..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt32Array.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Uint32Array typed array represents an array of 32-bit unsigned - * integers in the platform byte order. - */ -public class UInt32Array extends TypedArray { - - /** - * Creates an UInt32Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public UInt32Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a UInt32Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public UInt32Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 32-bit unsigned integer at the given index. - * - * @param index The index at which to return the value. - * @return The 32-bit unsigned integer at the index. - */ - public long get(final int index) { - return 0x00000000FFFFFFFF & buffer.asIntBuffer().get(index); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.asIntBuffer().limit(); - } - - /** - * Puts a 32-bit unsigned integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 32-bit unsigned integer to put into buffer. - */ - public void put(final int index, final long value) { - buffer.asIntBuffer().put(index, (int) (0x00000000FFFFFFFF & value)); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.UNSIGNED_INT_32_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java deleted file mode 100644 index 86e14ca..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8Array.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Uint8Array typed array represents an array of 8-bit unsigned integers - */ -public class UInt8Array extends TypedArray { - - /** - * Creates an UInt8Array projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public UInt8Array(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a UInt8Array projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public UInt8Array(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 8-bit unsigned integer at the given index. - * - * @param index The index at which to return the value. - * @return The 8-bit unsigned integer at the index. - */ - public short get(final int index) { - return (short) (0xFF & buffer.get(index)); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.limit(); - } - - /** - * Puts a 8-bit unsigned integer at a particular index. - * - * @param index The index at which to place the value. - * @param value The 8-bit unsigned integer to put into buffer. - */ - public void put(final int index, final short value) { - buffer.put(index, (byte) (0x00FF & value)); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.UNSIGNED_INT_8_ARRAY; - } - -} diff --git a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java b/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java deleted file mode 100644 index 7327ee6..0000000 --- a/src/main/java/com/eclipsesource/v8/utils/typedarrays/UInt8ClampedArray.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * EclipseSource - initial API and implementation - ******************************************************************************/ -package com.eclipsesource.v8.utils.typedarrays; - -import java.nio.ByteBuffer; - -import com.eclipsesource.v8.V8Value; - -/** - * The Uint8ClampedArray typed array represents an array of 8-bit unsigned - * integers clamped to 0-255; if you specified a value that is out of the - * range of [0,255], 0 or 255 will be set instead. - */ -public class UInt8ClampedArray extends TypedArray { - - /** - * Creates an UInt8ClampedArray projected onto the given ByteBuffer. - * - * @param buffer The ByteBuffer on which the array is projected on. - */ - public UInt8ClampedArray(final ByteBuffer buffer) { - super(buffer); - } - - /** - * Creates a UInt8ClampedArray projected onto the given ArrayBuffer. - * - * @param arrayBuffer The ArrayBuffer on which the array is projected on. - */ - public UInt8ClampedArray(final ArrayBuffer arrayBuffer) { - this(arrayBuffer.getByteBuffer()); - } - - /** - * Returns the 8-bit unsigned integer at the given index. - * - * @param index The index at which to return the value. - * @return The 8-bit unsigned integer at the index. - */ - public short get(final int index) { - return (short) (0xFF & buffer.get(index)); - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#length() - */ - @Override - public int length() { - return buffer.limit(); - } - - /** - * Puts a 8-bit unsigned integer at a particular index. If the unsigned - * integer is outside the range [0,255], 0 or 255 will be used instead. - * - * @param index The index at which to place the value. - * @param value The 8-bit unsigned integer to put into buffer. - */ - public void put(final int index, final short value) { - if (value > 255) { - buffer.put(index, (byte) (255)); - } else if (value < 0) { - buffer.put(index, (byte) (0)); - } else { - buffer.put(index, (byte) (value)); - } - } - - /* - * (non-Javadoc) - * @see com.eclipsesource.v8.utils.typedarrays.TypedArray#getType() - */ - @Override - public int getType() { - return V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY; - } - -} diff --git a/src/main/jni/com_eclipsesource_v8_V8Impl.cpp b/src/main/jni/com_eclipsesource_v8_V8Impl.cpp index faa142d..58e748b 100644 --- a/src/main/jni/com_eclipsesource_v8_V8Impl.cpp +++ b/src/main/jni/com_eclipsesource_v8_V8Impl.cpp @@ -8,35 +8,49 @@ * Contributors: * EclipseSource - initial API and implementation ******************************************************************************/ -#include "hybrid-log.h" #include #include #include #include +#include +#include #include #include #include #include "com_eclipsesource_v8_V8Impl.h" -#ifdef NODE_COMPATIBLE - #include - #include -#endif - #define TAG "J2V8_V8Impl" -//#pragma comment(lib, "userenv.lib") -//#pragma comment(lib, "IPHLPAPI.lib") -//#pragma comment(lib, "Ws2_32.lib") -//#pragma comment(lib, "WINMM.lib") -//#pragma comment( lib, "psapi.lib" ) + +#pragma comment(lib, "userenv.lib") +#pragma comment(lib, "IPHLPAPI.lib") +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "WINMM.lib") +#pragma comment( lib, "psapi.lib" ) using namespace std; using namespace v8; +inline std::string convertStringViewToSTDString(Isolate* isolate, const v8_inspector::StringView stringView) { + int length = static_cast(stringView.length()); + v8::Local message = ( + stringView.is8Bit() + ? v8::String::NewFromOneByte(isolate, reinterpret_cast(stringView.characters8()), v8::NewStringType::kNormal, length) + : v8::String::NewFromTwoByte(isolate, reinterpret_cast(stringView.characters16()), v8::NewStringType::kNormal, length) + ).ToLocalChecked(); + v8::String::Utf8Value result(isolate, message); + return *result; +} + +inline v8_inspector::StringView convertSTDStringToStringView(const std::string &str) { + auto* stringView = reinterpret_cast(str.c_str()); + return { stringView, str.length() }; +} + class MethodDescriptor { public: jlong methodID; jlong v8RuntimePtr; + Persistent obj; }; class WeakReferenceDescriptor { @@ -45,6 +59,137 @@ class WeakReferenceDescriptor { jlong objectHandle; }; +class InspectorDelegate { +public: + InspectorDelegate(const function &onResponse, const function &waitFrontendMessage) { + onResponse_ = onResponse; + waitFrontendMessage_ = waitFrontendMessage; + } + + void emitOnResponse(string message) { + onResponse_(message); + } + + void emitWaitFrontendMessage() { + waitFrontendMessage_(); + } + +private: + std::function onResponse_; + std::function waitFrontendMessage_; +}; + +class V8InspectorChannelImpl final: public v8_inspector::V8Inspector::Channel +{ +public: + V8InspectorChannelImpl(Isolate* isolate, InspectorDelegate* inspectorDelegate) { + isolate_ = isolate; + inspectorDelegate_ = inspectorDelegate; + } + + void sendResponse(int, unique_ptr message) override { + const std::string response = convertStringViewToSTDString(isolate_, message->string()); + inspectorDelegate_->emitOnResponse(response); + } + + void sendNotification(unique_ptr message) override { + const std::string notification = convertStringViewToSTDString(isolate_, message->string()); + inspectorDelegate_->emitOnResponse(notification); + } + + void flushProtocolNotifications() override {} + + uint8_t waitFrontendMessageOnPause() { + inspectorDelegate_->emitWaitFrontendMessage(); + return 1; + } + +private: + v8::Isolate* isolate_; + InspectorDelegate* inspectorDelegate_; +}; + +class V8InspectorClientImpl final: public v8_inspector::V8InspectorClient { +public: + V8InspectorClientImpl(Isolate* isolate, const std::unique_ptr &platform, InspectorDelegate* inspectorDelegate, std::string contextName) { + isolate_ = isolate; + context_ = isolate->GetCurrentContext(); + platform_ = platform.get(); + channel_ = std::unique_ptr(new V8InspectorChannelImpl(isolate, inspectorDelegate)); + inspector_ = v8_inspector::V8Inspector::create(isolate, this); + session_ = inspector_->connect(kContextGroupId, channel_.get(), v8_inspector::StringView()); + context_->SetAlignedPointerInEmbedderData(1, this); + + inspector_->contextCreated( + v8_inspector::V8ContextInfo(isolate->GetCurrentContext(), + kContextGroupId, + convertSTDStringToStringView(contextName)) + ); + } + + void dispatchProtocolMessage(const v8_inspector::StringView &message_view) { + session_->dispatchProtocolMessage(message_view); + } + + void runMessageLoopOnPause(int) override { + if (run_nested_loop_) { + return; + } + terminated_ = false; + run_nested_loop_ = true; + while (!terminated_ && channel_->waitFrontendMessageOnPause()) { + while (v8::platform::PumpMessageLoop(platform_, isolate_)) {} + } + terminated_ = true; + run_nested_loop_ = false; + } + + void quitMessageLoopOnPause() override { + terminated_ = true; + } + + void schedulePauseOnNextStatement(const v8_inspector::StringView &reason) { + session_->schedulePauseOnNextStatement(reason, reason); + } + +private: + static const int kContextGroupId = 1; + v8::Isolate* isolate_; + v8::Handle context_; + v8::Platform* platform_; + unique_ptr inspector_; + unique_ptr session_; + unique_ptr channel_; + uint8_t terminated_ = 0; + uint8_t run_nested_loop_ = 0; +}; + +class V8Inspector { +public: + jobject delegate = nullptr; + V8InspectorClientImpl* client = nullptr; + + void dispatchProtocolMessage(const std::string &message) { + if (client == nullptr) { + return; + } + v8_inspector::StringView protocolMessage = convertSTDStringToStringView(message); + client->dispatchProtocolMessage(protocolMessage); + } + + void schedulePauseOnNextStatement(const std::string reason) { + if (client == nullptr) { + return; + } + auto reason_ = convertSTDStringToStringView(reason); + client->schedulePauseOnNextStatement(reason_); + } + + void onResponse(const string& message); + + void waitFrontendMessage(); +}; + class V8Runtime { public: Isolate* isolate; @@ -53,88 +198,78 @@ class V8Runtime { Locker* locker; jobject v8; jthrowable pendingException; - -#ifdef NODE_COMPATIBLE - node::Environment* nodeEnvironment; - node::IsolateData* isolateData; - uv_loop_t* uvLoop; - bool running; -#endif - + V8Inspector* inspector; }; -template -static inline Local ToLocal(MaybeLocal maybe) { - Local v; - if (maybe.ToLocal(&v)) { - } - return v; -} - std::unique_ptr v8Platform = nullptr; const char* ToCString(const String::Utf8Value& value) { return *value ? *value : ""; } -JavaVM* jvm = NULL; -jclass v8cls = NULL; -jclass v8ObjectCls = NULL; -jclass v8ArrayCls = NULL; -jclass v8TypedArrayCls = NULL; -jclass v8ArrayBufferCls = NULL; -jclass v8FunctionCls = NULL; -jclass undefinedV8ObjectCls = NULL; -jclass undefinedV8ArrayCls = NULL; -jclass v8ResultsUndefinedCls = NULL; -jclass v8ScriptCompilationCls = NULL; -jclass v8ScriptExecutionException = NULL; -jclass v8RuntimeExceptionCls = NULL; -jclass throwableCls = NULL; -jclass stringCls = NULL; -jclass integerCls = NULL; -jclass doubleCls = NULL; -jclass booleanCls = NULL; -jclass errorCls = NULL; -jclass unsupportedOperationExceptionCls = NULL; -jmethodID v8ArrayInitMethodID = NULL; -jmethodID v8TypedArrayInitMethodID = NULL; -jmethodID v8ArrayBufferInitMethodID = NULL; -jmethodID v8ArrayGetHandleMethodID = NULL; -jmethodID v8CallVoidMethodID = NULL; -jmethodID v8ObjectReleaseMethodID = NULL; -jmethodID v8DisposeMethodID = NULL; -jmethodID v8WeakReferenceReleased = NULL; -jmethodID v8ArrayReleaseMethodID = NULL; -jmethodID v8ObjectIsUndefinedMethodID = NULL; -jmethodID v8ObjectGetHandleMethodID = NULL; -jmethodID throwableGetMessageMethodID = NULL; -jmethodID integerIntValueMethodID = NULL; -jmethodID booleanBoolValueMethodID = NULL; -jmethodID doubleDoubleValueMethodID = NULL; -jmethodID v8CallObjectJavaMethodMethodID = NULL; -jmethodID v8ScriptCompilationInitMethodID = NULL; -jmethodID v8ScriptExecutionExceptionInitMethodID = NULL; -jmethodID undefinedV8ArrayInitMethodID = NULL; -jmethodID undefinedV8ObjectInitMethodID = NULL; -jmethodID integerInitMethodID = NULL; -jmethodID doubleInitMethodID = NULL; -jmethodID booleanInitMethodID = NULL; -jmethodID v8FunctionInitMethodID = NULL; -jmethodID v8ObjectInitMethodID = NULL; -jmethodID v8RuntimeExceptionInitMethodID = NULL; - -void throwParseException(const Local& context, JNIEnv *env, Isolate* isolate, TryCatch* tryCatch); -void throwExecutionException(const Local& context, JNIEnv *env, Isolate* isolate, TryCatch* tryCatch, jlong v8RuntimePtr); +JavaVM* jvm = nullptr; +jclass v8cls = nullptr; +jclass v8InspectorCls = nullptr; +jclass v8InspectorDelegateCls = nullptr; +jclass v8ObjectCls = nullptr; +jclass v8ArrayCls = nullptr; +jclass v8TypedArrayCls = nullptr; +jclass v8ArrayBufferCls = nullptr; +jclass v8FunctionCls = nullptr; +jclass undefinedV8ObjectCls = nullptr; +jclass undefinedV8ArrayCls = nullptr; +jclass v8ResultsUndefinedCls = nullptr; +jclass v8ScriptCompilationCls = nullptr; +jclass v8ScriptExecutionException = nullptr; +jclass v8RuntimeExceptionCls = nullptr; +jclass throwableCls = nullptr; +jclass stringCls = nullptr; +jclass integerCls = nullptr; +jclass doubleCls = nullptr; +jclass booleanCls = nullptr; +jclass errorCls = nullptr; +jclass unsupportedOperationExceptionCls = nullptr; +jmethodID v8ArrayInitMethodID = nullptr; +jmethodID v8TypedArrayInitMethodID = nullptr; +jmethodID v8ArrayBufferInitMethodID = nullptr; +jmethodID v8ArrayGetHandleMethodID = nullptr; +jmethodID v8CallVoidMethodID = nullptr; +jmethodID v8ObjectReleaseMethodID = nullptr; +jmethodID v8DisposeMethodID = nullptr; +jmethodID v8WeakReferenceReleased = nullptr; +jmethodID v8ArrayReleaseMethodID = nullptr; +jmethodID v8ObjectIsUndefinedMethodID = nullptr; +jmethodID v8ObjectGetHandleMethodID = nullptr; +jmethodID throwableGetMessageMethodID = nullptr; +jmethodID integerIntValueMethodID = nullptr; +jmethodID booleanBoolValueMethodID = nullptr; +jmethodID doubleDoubleValueMethodID = nullptr; +jmethodID v8CallObjectJavaMethodMethodID = nullptr; +jmethodID v8ScriptCompilationInitMethodID = nullptr; +jmethodID v8ScriptExecutionExceptionInitMethodID = nullptr; +jmethodID undefinedV8ArrayInitMethodID = nullptr; +jmethodID undefinedV8ObjectInitMethodID = nullptr; +jmethodID integerInitMethodID = nullptr; +jmethodID doubleInitMethodID = nullptr; +jmethodID booleanInitMethodID = nullptr; +jmethodID v8FunctionInitMethodID = nullptr; +jmethodID v8ObjectInitMethodID = nullptr; +jmethodID v8RuntimeExceptionInitMethodID = nullptr; +jmethodID v8InspectorDelegateOnResponseMethodID = nullptr; +jmethodID v8InspectorDelegateWaitFrontendMessageMethodID = nullptr; + +void throwParseException(JNIEnv *env, const Local& context, Isolate* isolate, TryCatch* tryCatch); +void throwExecutionException(JNIEnv *env, const Local& context, Isolate* isolate, TryCatch* tryCatch, jlong v8RuntimePtr); void throwError(JNIEnv *env, const char *message); +void disposeMethod(v8::WeakCallbackInfo const& data); void throwV8RuntimeException(JNIEnv *env, String::Value *message); void throwResultUndefinedException(JNIEnv *env, const char *message); Isolate* getIsolate(JNIEnv *env, jlong handle); int getType(Handle v8Value); -jobject getResult(const Local& context, JNIEnv *env, jobject &v8, jlong v8RuntimePtr, Handle &result, jint expectedType); +jobject getResult(JNIEnv *env, const Local& context, jobject &v8, jlong v8RuntimePtr, Handle &result, jint expectedType); #define SETUP(env, v8RuntimePtr, errorReturnResult) getIsolate(env, v8RuntimePtr);\ - if ( isolate == NULL ) {\ + if ( isolate == nullptr ) {\ return errorReturnResult;\ }\ V8Runtime* runtime = reinterpret_cast(v8RuntimePtr);\ @@ -181,28 +316,45 @@ JNIEXPORT jstring JNICALL Java_com_eclipsesource_v8_V8__1getVersion (JNIEnv *env return env->NewStringUTF(utfString); } + +JNIEXPORT jstring JNICALL Java_com_eclipsesource_v8_V8__1getConstructorName +(JNIEnv *env, jobject, jlong v8RuntimePtr, jlong objectHandle) { + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) + Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); + String::Value unicodeString(isolate, object->GetConstructorName()); + return env->NewString(*unicodeString, unicodeString.length()); +} + Local createV8String(JNIEnv *env, Isolate *isolate, jstring &string) { - const uint16_t* unicodeString = env->GetStringChars(string, NULL); + const uint16_t* unicodeString = env->GetStringChars(string, nullptr); int length = env->GetStringLength(string); - Local result = ToLocal(String::NewFromTwoByte(isolate, unicodeString, v8::NewStringType::kNormal, length)); + MaybeLocal twoByteString = String::NewFromTwoByte(isolate, unicodeString, v8::NewStringType::kNormal, length); + if (twoByteString.IsEmpty()) { + return Local(); + } + Local result = twoByteString.ToLocalChecked(); env->ReleaseStringChars(string, unicodeString); return result; } -Handle getValueWithKey(const Local& context, JNIEnv* env, Isolate* isolate, jlong &v8RuntimePtr, jlong &objectHandle, jstring &key) { - Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); +std::string createString(JNIEnv *env, Isolate *isolate, jstring &str) { + Local v8Str = createV8String(env, isolate, str); + v8::String::Utf8Value stdString(isolate, v8Str); + return ToCString(stdString); +} + +Handle getValueWithKey(JNIEnv* env, const Local& context, Isolate* isolate, jlong &v8RuntimePtr, jlong &objectHandle, jstring &key) { + Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); Local v8Key = createV8String(env, isolate, key); - return ToLocal(object->Get(context, v8Key)); + return object->Get(context, v8Key).ToLocalChecked(); } -void addValueWithKey(const Local& context, JNIEnv* env, Isolate* isolate, jlong &v8RuntimePtr, jlong &objectHandle, jstring &key, Handle value) { - Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); +void addValueWithKey(JNIEnv* env, const Local context, Isolate* isolate, jlong &v8RuntimePtr, jlong &objectHandle, jstring &key, Handle value) { + Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); const uint16_t* unicodeString_key = env->GetStringChars(key, NULL); int length = env->GetStringLength(key); - Local v8Key = ToLocal(String::NewFromTwoByte(isolate, unicodeString_key, v8::NewStringType::kNormal, length)); - v8::Maybe unused_result = object->Set(context, v8Key, value); - if(unused_result.IsNothing()){ - } + Local v8Key = String::NewFromTwoByte(isolate, unicodeString_key, v8::NewStringType::kNormal, length).ToLocalChecked(); + object->Set(context, v8Key, value); env->ReleaseStringChars(key, unicodeString_key); } @@ -212,7 +364,7 @@ void getJNIEnv(JNIEnv*& env) { #ifdef __ANDROID_API__ if (jvm->AttachCurrentThread(&env, NULL) != 0) { #else - if (jvm->AttachCurrentThread((void **)&env, NULL) != 0) { + if (jvm->AttachCurrentThread((void **)&env, nullptr) != 0) { #endif std::cout << "Failed to attach" << std::endl; } @@ -239,23 +391,17 @@ class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator { virtual void Free(void* data, size_t) { free(data); } }; -#include "hybrid-hook.h" //HYBRID -// HYBRID ADD BEGIN: -#if defined(SUPPORT_J2V8RUNTIME) -extern "C" int InitJavaJsRuntime(JavaVM* vm, JNIEnv* env); -#endif -// HYBRID ADD END - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void*) { JNIEnv *env; jint onLoad_err = -1; if ( vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK ) { return onLoad_err; } - if (env == NULL) { + if (env == nullptr) { return onLoad_err; } - v8::V8::InitializeICUDefaultLocation("", nullptr); + + v8::V8::InitializeICU(); v8Platform = v8::platform::NewDefaultPlatform(); v8::V8::InitializePlatform(v8Platform.get()); v8::V8::Initialize(); @@ -263,6 +409,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { // on first creation, store the JVM and a handle to J2V8 classes jvm = vm; v8cls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/V8")); + v8InspectorCls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/inspector/V8Inspector")); + v8InspectorDelegateCls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/inspector/V8InspectorDelegate")); v8ObjectCls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/V8Object")); v8ArrayCls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/V8Array")); v8TypedArrayCls = (jclass)env->NewGlobalRef((env)->FindClass("com/eclipsesource/v8/V8TypedArray")); @@ -284,7 +432,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { // Get all method IDs v8ArrayInitMethodID = env->GetMethodID(v8ArrayCls, "", "(Lcom/eclipsesource/v8/V8;)V"); - v8TypedArrayInitMethodID = env->GetMethodID(v8TypedArrayCls, "", "(Lcom/eclipsesource/v8/V8;)V"); + v8TypedArrayInitMethodID = env->GetMethodID(v8TypedArrayCls, "", "(Lcom/eclipsesource/v8/V8;)V"); v8ArrayBufferInitMethodID = env->GetMethodID(v8ArrayBufferCls, "", "(Lcom/eclipsesource/v8/V8;Ljava/nio/ByteBuffer;)V"); v8ArrayGetHandleMethodID = env->GetMethodID(v8ArrayCls, "getHandle", "()J"); v8CallVoidMethodID = (env)->GetMethodID(v8cls, "callVoidJavaMethod", "(JLcom/eclipsesource/v8/V8Object;Lcom/eclipsesource/v8/V8Array;)V"); @@ -310,207 +458,121 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { v8FunctionInitMethodID = env->GetMethodID(v8FunctionCls, "", "(Lcom/eclipsesource/v8/V8;)V"); v8ObjectInitMethodID = env->GetMethodID(v8ObjectCls, "", "(Lcom/eclipsesource/v8/V8;)V"); - // HYBRID ADD BEGIN: -#if defined(SUPPORT_J2V8RUNTIME) - InitJavaJsRuntime(vm, env); -#endif - // HYBRID ADD END + v8InspectorDelegateOnResponseMethodID = env->GetMethodID(v8InspectorDelegateCls, "onResponse", "(Ljava/lang/String;)V"); + v8InspectorDelegateWaitFrontendMessageMethodID = env->GetMethodID(v8InspectorDelegateCls, "waitFrontendMessageOnPause", "()V"); + return JNI_VERSION_1_6; } +void V8Inspector::onResponse(const string& message) { + JNIEnv * env; + getJNIEnv(env); + env->CallVoidMethod(delegate, v8InspectorDelegateOnResponseMethodID, env->NewStringUTF(message.c_str())); +} + +void V8Inspector::waitFrontendMessage() { + JNIEnv * env; + getJNIEnv(env); + env->CallVoidMethod(delegate, v8InspectorDelegateWaitFrontendMessageMethodID); +} + JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1setFlags (JNIEnv *env, jclass, jstring v8flags) { if (v8flags) { - char const* str = env->GetStringUTFChars(v8flags, NULL); + char const* str = env->GetStringUTFChars(v8flags, nullptr); v8::V8::SetFlagsFromString(str, env->GetStringUTFLength(v8flags)); env->ReleaseStringUTFChars(v8flags, str); + v8::V8::Initialize(); } - v8::V8::Initialize(); } -ShellArrayBufferAllocator array_buffer_allocator; - -#ifdef NODE_COMPATIBLE -extern "C" { - void _register_async_wrap(void); - void _register_cares_wrap(void); - void _register_fs_event_wrap(void); - void _register_js_stream(void); - void _register_buffer(void); - void _register_config(void); - void _register_contextify(void); - void _register_crypto(void); - void _register_fs(void); - void _register_http_parser(void); - void _register_icu(void); - void _register_os(void); - void _register_url(void); - void _register_util(void); - void _register_v8(void); - void _register_zlib(void); - void _register_pipe_wrap(void); - void _register_process_wrap(void); - void _register_signal_wrap(void); - void _register_spawn_sync(void); - void _register_stream_wrap(void); - void _register_tcp_wrap(void); - void _register_timer_wrap(void); - void _register_tls_wrap(void); - void _register_tty_wrap(void); - void _register_udp_wrap(void); - void _register_uv(void); - } -#endif - +JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1getBuildID + (JNIEnv *, jclass) { + return 2; +} JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1startNodeJS - (JNIEnv * jniEnv, jclass, jlong v8RuntimePtr, jstring fileName) { -#ifdef NODE_COMPATIBLE - Isolate* isolate = SETUP(jniEnv, v8RuntimePtr, ); - setvbuf(stderr, NULL, _IOLBF, 1024); - const char* utfFileName = jniEnv->GetStringUTFChars(fileName, NULL); - const char *argv[] = {"j2v8", utfFileName, NULL}; - int argc = sizeof(argv) / sizeof(char*) - 1; - V8Runtime* rt = reinterpret_cast(v8RuntimePtr); - if (v8RuntimePtr == 1) { - #if defined(_MSC_VER) - // This is deadcode, but it ensures that libj2v8 'touches' all the - // node modules. If the node modules are not 'touched' then the - // linker will strip them out - // @node-builtins-force-link - _register_async_wrap(); - _register_cares_wrap(); - _register_fs_event_wrap(); - _register_js_stream(); - _register_buffer(); - _register_config(); - _register_contextify(); - _register_crypto(); - _register_fs(); - _register_http_parser(); - _register_icu(); - _register_os(); - _register_url(); - _register_util(); - _register_v8(); - _register_zlib(); - _register_pipe_wrap(); - _register_process_wrap(); - _register_signal_wrap(); - _register_spawn_sync(); - _register_stream_wrap(); - _register_tcp_wrap(); - _register_timer_wrap(); - _register_tls_wrap(); - _register_tty_wrap(); - _register_udp_wrap(); - _register_uv(); - #endif - } - rt->uvLoop = uv_default_loop(); - rt->isolateData = node::CreateIsolateData(isolate, rt->uvLoop); - node::Environment* env = node::CreateEnvironment(rt->isolateData, context, argc, argv, 0, 0); - node::LoadEnvironment(env); - rt->nodeEnvironment = env; - - rt->running = true; -#endif -#ifndef NODE_COMPATIBLE - (jniEnv)->ThrowNew(unsupportedOperationExceptionCls, "StartNodeJS Not Supported."); -#endif + (JNIEnv * env, jclass, jlong, jstring) { + (env)->ThrowNew(unsupportedOperationExceptionCls, "startNodeJS Not Supported."); } JNIEXPORT jboolean JNICALL Java_com_eclipsesource_v8_V8__1pumpMessageLoop - (JNIEnv * env, jclass, jlong v8RuntimePtr) { -#ifdef NODE_COMPATIBLE - Isolate* isolate = SETUP(env, v8RuntimePtr, false); - V8Runtime* rt = reinterpret_cast(v8RuntimePtr); - node::Environment* environment = rt->nodeEnvironment; - SealHandleScope seal(isolate); - v8::platform::PumpMessageLoop(v8Platform, isolate); - rt->running = uv_run(rt->uvLoop, UV_RUN_ONCE); - if (rt->running == false) { - v8::platform::PumpMessageLoop(v8Platform, isolate); - node::EmitBeforeExit(environment); - // Emit `beforeExit` if the loop became alive either after emitting - // event, or after running some callbacks. - rt->running = uv_loop_alive(rt->uvLoop); - if (uv_run(rt->uvLoop, UV_RUN_NOWAIT) != 0) { - rt->running = true; - } - } - return rt->running; -#endif -#ifndef NODE_COMPATIBLE - (env)->ThrowNew(unsupportedOperationExceptionCls, "pumpMessageLoop Not Supported."); - return false; -#endif + (JNIEnv * env, jclass, jlong) { + (env)->ThrowNew(unsupportedOperationExceptionCls, "pumpMessageLoop Not Supported."); + return false; } JNIEXPORT jboolean JNICALL Java_com_eclipsesource_v8_V8__1isRunning (JNIEnv *env, jclass, jlong v8RuntimePtr) { - #ifdef NODE_COMPATIBLE - Isolate* isolate = SETUP(env, v8RuntimePtr, false); - V8Runtime* rt = reinterpret_cast(v8RuntimePtr); - return rt->running; - #endif - #ifndef NODE_COMPATIBLE - (env)->ThrowNew(unsupportedOperationExceptionCls, "isRunning Not Supported."); - return false; - #endif + (env)->ThrowNew(unsupportedOperationExceptionCls, "isRunning Not Supported."); + return false; } JNIEXPORT jboolean JNICALL Java_com_eclipsesource_v8_V8__1isNodeCompatible - (JNIEnv *, jclass) { - #ifdef NODE_COMPATIBLE - return true; - #else + (JNIEnv * env, jclass) { + (env)->ThrowNew(unsupportedOperationExceptionCls, "isNodeCompatible Not Supported."); return false; - #endif } JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1createIsolate - (JNIEnv *env, jobject v8, jstring globalAlias, jstring nativejsSnapshotSoName) { - V8Runtime* runtime = new V8Runtime(); - v8::Isolate::CreateParams create_params; - create_params.array_buffer_allocator = &array_buffer_allocator; - if (nativejsSnapshotSoName != NULL) { - const char* nativejs_snapshot_so_name = - env->GetStringUTFChars(nativejsSnapshotSoName, NULL); - create_params.snapshot_blob = const_cast - (hybrid::GetCustomJsSnapshot(nativejs_snapshot_so_name)); - env->ReleaseStringUTFChars(nativejsSnapshotSoName, nativejs_snapshot_so_name); - } - runtime->isolate = v8::Isolate::New(create_params); - runtime->locker = new Locker(runtime->isolate); - { + (JNIEnv *env, jobject v8, jstring globalAlias) { + V8Runtime* runtime = new V8Runtime(); + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); + runtime->isolate = v8::Isolate::New(create_params); + Locker locker(runtime->isolate); v8::Isolate::Scope isolate_scope(runtime->isolate); runtime->v8 = env->NewGlobalRef(v8); - runtime->pendingException = NULL; + runtime->pendingException = nullptr; HandleScope handle_scope(runtime->isolate); Handle globalObject = ObjectTemplate::New(runtime->isolate); - if (globalAlias == NULL) { - Handle context = Context::New(runtime->isolate, NULL, globalObject); + if (globalAlias == nullptr) { + Handle context = Context::New(runtime->isolate, nullptr, globalObject); runtime->context_.Reset(runtime->isolate, context); runtime->globalObject = new Persistent; - runtime->globalObject->Reset(runtime->isolate, ToLocal(context->Global()->GetPrototype()->ToObject(context))); + runtime->globalObject->Reset(runtime->isolate, context->Global()->GetPrototype()->ToObject(context).ToLocalChecked()); } else { Local utfAlias = createV8String(env, runtime->isolate, globalAlias); globalObject->SetAccessor(utfAlias, jsWindowObjectAccessor); - Handle context = Context::New(runtime->isolate, NULL, globalObject); + Handle context = Context::New(runtime->isolate, nullptr, globalObject); runtime->context_.Reset(runtime->isolate, context); runtime->globalObject = new Persistent; - runtime->globalObject->Reset(runtime->isolate, ToLocal(context->Global()->GetPrototype()->ToObject(context))); + runtime->globalObject->Reset(runtime->isolate, context->Global()->GetPrototype()->ToObject(context).ToLocalChecked()); } + return reinterpret_cast(runtime); +} - // HYBRID ADD - hybrid::OnCreateIsolate(reinterpret_cast(runtime)); - } +JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1createInspector + (JNIEnv *env, jobject, jlong v8RuntimePtr, jobject inspectorDelegateObj, jstring jcontextName) { + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) - delete(runtime->locker); - runtime->locker = NULL; - return reinterpret_cast(runtime); + runtime->inspector = new V8Inspector(); + runtime->inspector->delegate = env->NewGlobalRef(inspectorDelegateObj); + + InspectorDelegate* delegate = new InspectorDelegate( + std::bind(&V8Inspector::onResponse, runtime->inspector, std::placeholders::_1), + std::bind(&V8Inspector::waitFrontendMessage, runtime->inspector) + ); + + std::string contextName = jcontextName != nullptr ? createString(env, runtime->isolate, jcontextName) : ""; + runtime->inspector->client = new V8InspectorClientImpl(runtime->isolate, v8Platform, delegate, contextName); + + return reinterpret_cast(runtime->inspector); +} + +JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1dispatchProtocolMessage + (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong v8InspectorPtr, jstring protocolMessage) { + Isolate* isolate = SETUP(env, v8RuntimePtr, ) + V8Inspector* inspector = reinterpret_cast(v8InspectorPtr); + inspector->dispatchProtocolMessage(createString(env, isolate, protocolMessage)); +} + +JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1schedulePauseOnNextStatement + (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong v8InspectorPtr, jstring reason) { + Isolate* isolate = SETUP(env, v8RuntimePtr, ) + V8Inspector* inspector = reinterpret_cast(v8InspectorPtr); + inspector->schedulePauseOnNextStatement(createString(env, isolate, reason)); } JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1acquireLock @@ -518,7 +580,7 @@ JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1acquireLock V8Runtime* runtime = reinterpret_cast(v8RuntimePtr); if(runtime->isolate->InContext()) { jstring exceptionString = env->NewStringUTF("Cannot acquire lock while in a V8 Context"); - jthrowable exception = (jthrowable)env->NewObject(v8RuntimeExceptionCls, v8RuntimeExceptionInitMethodID, exceptionString); + jthrowable exception = static_cast(env->NewObject(v8RuntimeExceptionCls, v8RuntimeExceptionInitMethodID, exceptionString)); (env)->Throw(exception); env->DeleteLocalRef(exceptionString); return; @@ -531,24 +593,31 @@ JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1releaseLock V8Runtime* runtime = reinterpret_cast(v8RuntimePtr); if(runtime->isolate->InContext()) { jstring exceptionString = env->NewStringUTF("Cannot release lock while in a V8 Context"); - jthrowable exception = (jthrowable)env->NewObject(v8RuntimeExceptionCls, v8RuntimeExceptionInitMethodID, exceptionString); + jthrowable exception = static_cast(env->NewObject(v8RuntimeExceptionCls, v8RuntimeExceptionInitMethodID, exceptionString)); (env)->Throw(exception); env->DeleteLocalRef(exceptionString); return; } delete(runtime->locker); - runtime->locker = NULL; + runtime->locker = nullptr; } JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1lowMemoryNotification - (JNIEnv *env, jobject, jlong v8RuntimePtr) { + (JNIEnv*, jobject, jlong v8RuntimePtr) { V8Runtime* runtime = reinterpret_cast(v8RuntimePtr); runtime->isolate->LowMemoryNotification(); } +JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initEmptyContainer +(JNIEnv *env, jobject, jlong v8RuntimePtr) { + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) + Persistent* container = new Persistent; + return reinterpret_cast(container); +} + JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Object (JNIEnv *env, jobject, jlong v8RuntimePtr) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Local obj = Object::New(isolate); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, obj); @@ -557,22 +626,20 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Object JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1getGlobalObject (JNIEnv *env, jobject, jlong v8RuntimePtr) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); - Local obj = Object::New(isolate); - obj.IsEmpty(); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) return reinterpret_cast(reinterpret_cast(v8RuntimePtr)->globalObject); } JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1createTwin (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong objectHandle, jlong twinObjectHandle) { - Isolate* isolate = SETUP(env, v8RuntimePtr, ); + Isolate* isolate = SETUP(env, v8RuntimePtr, ) Handle obj = Local::New(isolate, *reinterpret_cast*>(objectHandle)); reinterpret_cast*>(twinObjectHandle)->Reset(reinterpret_cast(v8RuntimePtr)->isolate, obj); } JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Array (JNIEnv *env, jobject, jlong v8RuntimePtr) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Local array = Array::New(isolate); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); @@ -581,9 +648,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int8Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Int8Array::New(arrayBuffer, offset, length); + Local array = Int8Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -591,9 +658,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int8Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt8Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Uint8Array::New(arrayBuffer, offset, length); + Local array = Uint8Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -601,9 +668,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt8Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt8ClampedArray (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Uint8ClampedArray::New(arrayBuffer, offset, length); + Local array = Uint8ClampedArray::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -611,9 +678,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt8ClampedArra JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int32Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Int32Array::New(arrayBuffer, offset, length); + Local array = Int32Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -621,9 +688,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int32Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt32Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Uint32Array::New(arrayBuffer, offset, length); + Local array = Uint32Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -631,9 +698,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt32Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt16Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Uint16Array::New(arrayBuffer, offset, length); + Local array = Uint16Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -641,9 +708,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8UInt16Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int16Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Int16Array::New(arrayBuffer, offset, length); + Local array = Int16Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -651,9 +718,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Int16Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Float32Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Float32Array::New(arrayBuffer, offset, length); + Local array = Float32Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -661,9 +728,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Float32Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Float64Array (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong bufferHandle, jint offset, jint length) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(bufferHandle)); - Local array = Float64Array::New(arrayBuffer, offset, length); + Local array = Float64Array::New(arrayBuffer, static_cast(offset), static_cast(length)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, array); return reinterpret_cast(container); @@ -671,8 +738,9 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8Float64Array JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8ArrayBuffer__JI (JNIEnv *env, jobject, jlong v8RuntimePtr, jint capacity) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); - Local arrayBuffer = ArrayBuffer::New(isolate, capacity); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) + std::unique_ptr backing_store = v8::ArrayBuffer::NewBackingStore(isolate, static_cast(capacity)); + Local arrayBuffer = ArrayBuffer::New(isolate, std::move(backing_store)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, arrayBuffer); return reinterpret_cast(container); @@ -680,8 +748,14 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8ArrayBuffer__JI JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8ArrayBuffer__JLjava_nio_ByteBuffer_2I (JNIEnv *env, jobject, jlong v8RuntimePtr, jobject byteBuffer, jint capacity) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); - Local arrayBuffer = ArrayBuffer::New(isolate, env->GetDirectBufferAddress(byteBuffer), capacity); + Isolate* isolate = SETUP(env, v8RuntimePtr, 0) + std::unique_ptr backing_store = ArrayBuffer::NewBackingStore( + env->GetDirectBufferAddress(byteBuffer), + static_cast(capacity), + [](void*, size_t, void*){}, + nullptr + ); + Local arrayBuffer = ArrayBuffer::New(isolate, std::move(backing_store)); Persistent* container = new Persistent; container->Reset(reinterpret_cast(v8RuntimePtr)->isolate, arrayBuffer); return reinterpret_cast(container); @@ -689,11 +763,10 @@ JNIEXPORT jlong JNICALL Java_com_eclipsesource_v8_V8__1initNewV8ArrayBuffer__JLj JNIEXPORT jobject JNICALL Java_com_eclipsesource_v8_V8__1createV8ArrayBufferBackingStore (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong objectHandle, jint capacity) { - Isolate* isolate = SETUP(env, v8RuntimePtr, 0); + Isolate* isolate = SETUP(env, v8RuntimePtr, nullptr) Handle arrayBuffer = Local::New(isolate, *reinterpret_cast*>(objectHandle)); - void* dataPtr = arrayBuffer->GetContents().Data(); - if(dataPtr){} - jobject byteBuffer = env->NewDirectByteBuffer(arrayBuffer->GetContents().Data(), capacity); + void* dataPtr = arrayBuffer->GetBackingStore()->Data(); + jobject byteBuffer = env->NewDirectByteBuffer(dataPtr, capacity); return byteBuffer; } @@ -711,12 +784,12 @@ JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1release JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1terminateExecution (JNIEnv * env, jobject, jlong v8RuntimePtr) { - if (v8RuntimePtr == 0) { - return; - } - Isolate* isolate = getIsolate(env, v8RuntimePtr); - isolate->TerminateExecution(); - return; + if (v8RuntimePtr == 0) { + return; + } + Isolate* isolate = getIsolate(env, v8RuntimePtr); + isolate->TerminateExecution(); + return; } JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1releaseRuntime @@ -724,14 +797,12 @@ JNIEXPORT void JNICALL Java_com_eclipsesource_v8_V8__1releaseRuntime if (v8RuntimePtr == 0) { return; } - hybrid::OnDestroyIsolate(reinterpret_cast(v8RuntimePtr)); - if (reinterpret_cast(v8RuntimePtr)->locker) { - delete(reinterpret_cast(v8RuntimePtr)->locker); - } + Isolate* isolate = getIsolate(env, v8RuntimePtr); reinterpret_cast(v8RuntimePtr)->context_.Reset(); reinterpret_cast(v8RuntimePtr)->isolate->Dispose(); env->DeleteGlobalRef(reinterpret_cast(v8RuntimePtr)->v8); - delete(reinterpret_cast(v8RuntimePtr)); + V8Runtime* runtime = reinterpret_cast(v8RuntimePtr); + delete(runtime); } JNIEXPORT jboolean JNICALL Java_com_eclipsesource_v8_V8__1contains @@ -739,79 +810,92 @@ JNIEXPORT jboolean JNICALL Java_com_eclipsesource_v8_V8__1contains Isolate* isolate = SETUP(env, v8RuntimePtr, false); Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); Local v8Key = createV8String(env, isolate, key); - return object->Has(context, v8Key).FromJust(); + return object->Has(context, v8Key).FromMaybe(false); } JNIEXPORT jobjectArray JNICALL Java_com_eclipsesource_v8_V8__1getKeys (JNIEnv *env, jobject, jlong v8RuntimePtr, jlong objectHandle) { Isolate* isolate = SETUP(env, v8RuntimePtr, NULL); Handle object = Local::New(isolate, *reinterpret_cast*>(objectHandle)); - Local properties = ToLocal(object->GetOwnPropertyNames(context)); - int size = properties->Length(); - jobjectArray keys = (env)->NewObjectArray(size, stringCls, NULL); - for (int i = 0; i < size; i++) { - String::Value unicodeString(isolate, ToLocal(properties->Get(context, i))); - jobject key = (env)->NewString(*unicodeString, unicodeString.length()); - (env)->SetObjectArrayElement(keys, i, key); - (env)->DeleteLocalRef(key); + MaybeLocal properties = object->GetOwnPropertyNames(context); + if (!properties.IsEmpty()) { + int size = properties.ToLocalChecked()->Length(); + jobjectArray keys = (env)->NewObjectArray(size, stringCls, nullptr); + for (int i = 0; i < size; i++) { + MaybeLocal property = properties.ToLocalChecked()->Get(context, i); + if (property.IsEmpty()) { + continue; + } + String::Value unicodeString(isolate, property.ToLocalChecked()); + jobject key = (env)->NewString(*unicodeString, unicodeString.length()); + (env)->SetObjectArrayElement(keys, i, key); + (env)->DeleteLocalRef(key); + } + return keys; } - return keys; + return (env)->NewObjectArray(0, stringCls, nullptr); } ScriptOrigin* createScriptOrigin(JNIEnv * env, Isolate* isolate, jstring &jscriptName, jint jlineNumber = 0) { Local scriptName = createV8String(env, isolate, jscriptName); - return new ScriptOrigin(scriptName, Integer::New(isolate, jlineNumber)); + return new ScriptOrigin(isolate, scriptName, jlineNumber); } bool compileScript(const Local& context, Isolate *isolate, jstring &jscript, JNIEnv *env, jstring jscriptName, jint &jlineNumber, Local