Browse Source
* commit 'ff2cf353b58b8b721bd7ff0c13c3574dc630e2f7': KERNEL-12469 js引擎j2v8剥离成独立插件 REPORT-78654 迁移报错优化 REPORT-78654 迁移报错优化persist/11.0
superman
2 years ago
73 changed files with 4 additions and 11106 deletions
@ -1,6 +0,0 @@
|
||||
*.iml |
||||
.idea/ |
||||
.DS_Store |
||||
.project |
||||
.classpath |
||||
*.gradle |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<parent> |
||||
<groupId>com.fr.third</groupId> |
||||
<artifactId>step1</artifactId> |
||||
<version>${revision}</version> |
||||
<relativePath>../base-third-project/base-third-step1</relativePath> |
||||
</parent> |
||||
|
||||
<artifactId>fine-j2v8</artifactId> |
||||
<version>${revision}</version> |
||||
|
||||
|
||||
</project> |
@ -1,37 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* Classes that implement this interface provide a method |
||||
* which can be invoked from JavaScript. The method can return |
||||
* a result. |
||||
* |
||||
* After creating an instance of a class that implements this |
||||
* interface it can be registered as a Callback on a V8Object. |
||||
*/ |
||||
public interface JavaCallback { |
||||
|
||||
/** |
||||
* Called when a JS Function invokes a the registered Java |
||||
* method. |
||||
* |
||||
* @param receiver The V8Object that the function was called on. |
||||
* @param parameters The parameters passed to the JS Function. The |
||||
* parameter array does not need to be released, by any objects accessed |
||||
* from the array must be. |
||||
* |
||||
* @return A result that should be passed back to JavaScript. The |
||||
* result must be either an Integer, Double, Boolean, String or V8Value. |
||||
*/ |
||||
public Object invoke(V8Object receiver, V8Array parameters); |
||||
|
||||
} |
@ -1,33 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* Classes that implement this interface provide a method |
||||
* which can be invoked from JavaScript. |
||||
* |
||||
* After creating an instance of a class that implements this |
||||
* interface it can be registered as a Callback on a V8Object. |
||||
*/ |
||||
public interface JavaVoidCallback { |
||||
|
||||
/** |
||||
* Called when a JS Function invokes a the registered Java |
||||
* method. |
||||
* |
||||
* @param receiver The V8Object that the function was called on. |
||||
* @param parameters The parameters passed to the JS Function. The |
||||
* parameter array does not need to be released, by any objects accessed |
||||
* from the array must be. |
||||
*/ |
||||
public void invoke(V8Object receiver, V8Array parameters); |
||||
|
||||
} |
@ -1,243 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
* Wolfgang Steiner - code separation PlatformDetector/LibraryLoader |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.lang.management.ManagementFactory; |
||||
|
||||
class LibraryLoader { |
||||
|
||||
static final String SEPARATOR; |
||||
static final String DELIMITER; |
||||
|
||||
static final String SWT_LIB_DIR = ".j2v8"; |
||||
|
||||
static final String MINIMUM_VERSION = "6.2"; |
||||
|
||||
static { |
||||
DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
|
||||
SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$
|
||||
} |
||||
|
||||
/** |
||||
* Returns the base-name for the native J2V8 library file. |
||||
* @param withLinuxVendor include/exclude the {vendor} part from the returned filename |
||||
* <p>NOTE: Vendors are only included for linux systems</p> |
||||
* @return The filename string has the following structure: |
||||
* <pre><code>{arch}-[vendor]-{operating_system}</pre></code> |
||||
*/ |
||||
public static String computeLibraryShortName(boolean withLinuxVendor) { |
||||
String prefix = "j2v8"; |
||||
String vendor = withLinuxVendor && PlatformDetector.OS.isLinux() ? PlatformDetector.Vendor.getName() : null; |
||||
String os = PlatformDetector.OS.getName(); |
||||
String arch = PlatformDetector.Arch.getName(); |
||||
|
||||
final String separator = "-"; |
||||
|
||||
return |
||||
prefix + |
||||
(vendor != null ? separator + vendor : "") + |
||||
separator + os + |
||||
separator + arch; |
||||
} |
||||
|
||||
public static String computeLibraryFullName(boolean withLinuxVendor) { |
||||
return "lib" + computeLibraryShortName(withLinuxVendor) + "." + PlatformDetector.OS.getLibFileExtension(); |
||||
} |
||||
|
||||
static boolean tryLoad(boolean withLinuxVendor, StringBuffer message) { |
||||
String libShortName = computeLibraryShortName(withLinuxVendor); |
||||
String libFullName = computeLibraryFullName(withLinuxVendor); |
||||
String ideLocation = System.getProperty("user.dir") + SEPARATOR + "jni" + SEPARATOR + libFullName; |
||||
|
||||
/* Try loading library from java library path */ |
||||
if (load(libFullName, message)) { |
||||
return true; |
||||
} |
||||
if (load(libShortName, message)) { |
||||
return true; |
||||
} |
||||
|
||||
/* Try loading library from the IDE location */ |
||||
if (new File(ideLocation).exists()) { |
||||
if (load(ideLocation, message)) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
static void loadLibrary(final String tempDirectory) { |
||||
if (PlatformDetector.OS.isAndroid()) { |
||||
System.loadLibrary("j2v8"); |
||||
return; |
||||
} |
||||
|
||||
StringBuffer message = new StringBuffer(); |
||||
|
||||
// try loading a vendor-specific library first
|
||||
if (tryLoad(true, message)) |
||||
return; |
||||
|
||||
// if there is no vendor-specific library, just try to load the default OS library
|
||||
if (tryLoad(false, message)) |
||||
return; |
||||
|
||||
String path = null; |
||||
|
||||
if (tempDirectory != null) { |
||||
path = tempDirectory; |
||||
} else { |
||||
path = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$
|
||||
} |
||||
|
||||
// try extracting a vendor-specific library first
|
||||
if (extract(path, true, message)) |
||||
return; |
||||
|
||||
// if there is no vendor-specific library, just try to extract the default OS library
|
||||
if (extract(path, false, message)) |
||||
return; |
||||
|
||||
/* Failed to find the library */ |
||||
throw new UnsatisfiedLinkError("Could not load J2V8 library. Reasons: " + message.toString()); //$NON-NLS-1$
|
||||
} |
||||
|
||||
static boolean load(final String libName, final StringBuffer message) { |
||||
try { |
||||
if (libName.indexOf(SEPARATOR) != -1) { |
||||
System.load(libName); |
||||
} else { |
||||
System.loadLibrary(libName); |
||||
} |
||||
return true; |
||||
} catch (UnsatisfiedLinkError e) { |
||||
if (message.length() == 0) { |
||||
message.append(DELIMITER); |
||||
} |
||||
message.append('\t'); |
||||
message.append(e.getMessage()); |
||||
message.append(DELIMITER); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static boolean extract(String libPath, boolean withLinuxVendor, StringBuffer message) { |
||||
String libFullName = computeLibraryFullName(withLinuxVendor); |
||||
return extract(libPath + SEPARATOR + libFullName, libFullName, message); |
||||
} |
||||
|
||||
static boolean extract(final String fileName, final String mappedName, final StringBuffer message) { |
||||
FileOutputStream os = null; |
||||
InputStream is = null; |
||||
File file = new File(fileName); |
||||
//这部分自己修改过,主要是以为linux通过System.getProperty("java.io.tmpdir")获取到的是相对路径,但是System.load方法加载需要文件的绝对路径。
|
||||
String absoluteName = file.getAbsolutePath(); |
||||
boolean extracted = false; |
||||
try { |
||||
if (file.exists()) { |
||||
file.delete(); |
||||
} |
||||
is = LibraryLoader.class.getResourceAsStream("/" + mappedName); //$NON-NLS-1$
|
||||
if (is != null) { |
||||
extracted = true; |
||||
int read; |
||||
byte[] buffer = new byte[4096]; |
||||
os = new FileOutputStream(fileName); |
||||
while ((read = is.read(buffer)) != -1) { |
||||
os.write(buffer, 0, read); |
||||
} |
||||
os.close(); |
||||
is.close(); |
||||
chmod("755", fileName); |
||||
if (load(absoluteName, message)) { |
||||
return true; |
||||
} |
||||
} |
||||
} catch (Throwable e) { |
||||
try { |
||||
if (os != null) { |
||||
os.close(); |
||||
} |
||||
} catch (IOException e1) { |
||||
} |
||||
try { |
||||
if (is != null) { |
||||
is.close(); |
||||
} |
||||
} catch (IOException e1) { |
||||
} |
||||
if (extracted && file.exists()) { |
||||
file.delete(); |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static void chmod(final String permision, final String path) { |
||||
if (PlatformDetector.OS.isWindows()) { |
||||
return; |
||||
} |
||||
try { |
||||
Runtime.getRuntime().exec(new String[] { "chmod", permision, path }).waitFor(); //$NON-NLS-1$
|
||||
} catch (Throwable e) { |
||||
} |
||||
} |
||||
|
||||
//内核版本windows NT6.2以下存在加载dll之后无法正常退出的问题,注册钩子函数退出时杀掉进程
|
||||
static void checkExceptionVersion() { |
||||
String version = System.getProperty("os.version"); |
||||
if (PlatformDetector.OS.isWindows() && belowMinimumVersion(version)) { |
||||
registerExit(); |
||||
} |
||||
} |
||||
|
||||
//低于指定版本,6.2以下
|
||||
private static boolean belowMinimumVersion(String version) { |
||||
return compareVersion(version, MINIMUM_VERSION) < 0; |
||||
} |
||||
|
||||
private static int compareVersion(String version1, String version2) { |
||||
String[] versionArray1 = version1.split("\\.");//注意此处为正则匹配,不能用".";
|
||||
String[] versionArray2 = version2.split("\\."); |
||||
int idx = 0; |
||||
int minLength = Math.min(versionArray1.length, versionArray2.length);//取最小长度值
|
||||
int diff = 0; |
||||
while (idx < minLength |
||||
&& (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0//先比较长度
|
||||
&& (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {//再比较字符
|
||||
++idx; |
||||
} |
||||
//如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
|
||||
diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length; |
||||
return diff; |
||||
} |
||||
|
||||
//低于指定版本,6.2以下
|
||||
private static void registerExit() { |
||||
Runtime.getRuntime().addShutdownHook(new Thread() { |
||||
@Override |
||||
public void run() { |
||||
String name = ManagementFactory.getRuntimeMXBean().getName(); |
||||
String pid = name.split("@")[0]; |
||||
try { |
||||
Runtime.getRuntime().exec("taskkill /F /PID " + pid); |
||||
} catch (Exception ignore) { |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -1,239 +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; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
|
||||
/** |
||||
* An isolate NodeJS runtime. |
||||
* |
||||
* This class is only available on some platforms. In particular any methods |
||||
* on this class, on an Android device, will lead to an UnsupportedOperationException. |
||||
*/ |
||||
public class NodeJS { |
||||
|
||||
private static final String TMP_JS_EXT = ".js.tmp"; |
||||
private static final String NEXT_TICK = "nextTick"; |
||||
private static final String PROCESS = "process"; |
||||
private static final String GLOBAL = "global"; |
||||
private static final String STARTUP_CALLBACK = "__run"; |
||||
private static final String STARTUP_SCRIPT = "global." + STARTUP_CALLBACK + "(require, exports, module, __filename, __dirname);"; |
||||
private static final String STARTUP_SCRIPT_NAME = "startup"; |
||||
private static final String VERSIONS = "versions"; |
||||
private static final String NODE = "node"; |
||||
private String nodeVersion = null; |
||||
|
||||
private V8 v8; |
||||
private V8Function require; |
||||
|
||||
/** |
||||
* Creates a NodeJS Runtime |
||||
* |
||||
* @return The NodeJS runtime. |
||||
* |
||||
* May throw an UnsupportedOperationException if node.js integration has not |
||||
* been compiled for your platform. |
||||
*/ |
||||
public static NodeJS createNodeJS() { |
||||
return createNodeJS(null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the version of Node.js that is runtime is built against. |
||||
* This uses process.versions.node to get the version. |
||||
* |
||||
* @return The version of Node.js. |
||||
*/ |
||||
public String getNodeVersion() { |
||||
if (nodeVersion != null) { |
||||
return nodeVersion; |
||||
} |
||||
V8Object process = null; |
||||
V8Object versions = null; |
||||
try { |
||||
process = v8.getObject(PROCESS); |
||||
versions = process.getObject(VERSIONS); |
||||
nodeVersion = versions.getString(NODE); |
||||
} finally { |
||||
safeRelease(process); |
||||
safeRelease(versions); |
||||
} |
||||
return nodeVersion; |
||||
} |
||||
|
||||
/** |
||||
* Creates a NodeJS runtime and executes a JS Script |
||||
* |
||||
* @param file The JavaScript to execute or null for no script. |
||||
* @return The NodeJS runtime. |
||||
* |
||||
* May throw an UnsupportedOperationException if node.js integration has not |
||||
* been compiled for your platform. |
||||
*/ |
||||
public static NodeJS createNodeJS(final File file) { |
||||
V8 v8 = V8.createV8Runtime(GLOBAL); |
||||
final NodeJS node = new NodeJS(v8); |
||||
v8.registerJavaMethod(new JavaVoidCallback() { |
||||
|
||||
@Override |
||||
public void invoke(final V8Object receiver, final V8Array parameters) { |
||||
V8Function require = (V8Function) parameters.get(0); |
||||
try { |
||||
node.init(require.twin()); |
||||
} finally { |
||||
require.close(); |
||||
} |
||||
} |
||||
}, STARTUP_CALLBACK); |
||||
try { |
||||
File startupScript = createTemporaryScriptFile(STARTUP_SCRIPT, STARTUP_SCRIPT_NAME); |
||||
try { |
||||
v8.createNodeRuntime(startupScript.getAbsolutePath()); |
||||
} finally { |
||||
startupScript.delete(); |
||||
} |
||||
} catch (IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
if (file != null) { |
||||
node.exec(file); |
||||
} |
||||
return node; |
||||
} |
||||
|
||||
/** |
||||
* Returns the V8 runtime being used for this NodeJS instance. |
||||
* |
||||
* @return The V8 Runtime. |
||||
*/ |
||||
public V8 getRuntime() { |
||||
return v8; |
||||
} |
||||
|
||||
/** |
||||
* Handles the next message in the message loop. Returns True |
||||
* if there are more messages to handle, false otherwise. |
||||
* |
||||
* @return True if there are more messages to handle, false otherwise. |
||||
*/ |
||||
public boolean handleMessage() { |
||||
v8.checkThread(); |
||||
return v8.pumpMessageLoop(); |
||||
} |
||||
|
||||
/** |
||||
* Releases the NodeJS runtime. |
||||
*/ |
||||
public void release() { |
||||
v8.checkThread(); |
||||
if (!require.isReleased()) { |
||||
require.close(); |
||||
} |
||||
if (!v8.isReleased()) { |
||||
v8.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns true if there are more messages to process, false otherwise. |
||||
* |
||||
* @return True if there are more messages to process, false otherwise. |
||||
*/ |
||||
public boolean isRunning() { |
||||
v8.checkThread(); |
||||
return v8.isRunning(); |
||||
} |
||||
|
||||
/** |
||||
* Invokes NodeJS require() on the specified file. This will load the module, execute |
||||
* it and return the exports object to the caller. The exports object must be released. |
||||
* |
||||
* @param file The module to load. |
||||
* @return The exports object. |
||||
*/ |
||||
public V8Object require(final File file) { |
||||
v8.checkThread(); |
||||
V8Array requireParams = new V8Array(v8); |
||||
try { |
||||
requireParams.push(file.getAbsolutePath()); |
||||
return (V8Object) require.call(null, requireParams); |
||||
} finally { |
||||
requireParams.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Execute a NodeJS script. This will load the script and execute it on the |
||||
* next tick. This is the same as how NodeJS executes scripts at startup. Since |
||||
* the script won't actually run until the next tick, this method does not return |
||||
* a result. |
||||
* |
||||
* @param file The script to execute. |
||||
*/ |
||||
public void exec(final File file) { |
||||
V8Function scriptExecution = createScriptExecutionCallback(file); |
||||
V8Object process = null; |
||||
V8Array parameters = null; |
||||
try { |
||||
process = v8.getObject(PROCESS); |
||||
parameters = new V8Array(v8); |
||||
parameters.push(scriptExecution); |
||||
process.executeObjectFunction(NEXT_TICK, parameters); |
||||
} finally { |
||||
safeRelease(process); |
||||
safeRelease(parameters); |
||||
safeRelease(scriptExecution); |
||||
} |
||||
} |
||||
|
||||
private V8Function createScriptExecutionCallback(final File file) { |
||||
V8Function v8Function = new V8Function(v8, new JavaCallback() { |
||||
@Override |
||||
public Object invoke(final V8Object receiver, final V8Array parameters) { |
||||
V8Array requireParams = new V8Array(v8); |
||||
try { |
||||
requireParams.push(file.getAbsolutePath()); |
||||
return require.call(null, requireParams); |
||||
} finally { |
||||
requireParams.close(); |
||||
} |
||||
} |
||||
}); |
||||
return v8Function; |
||||
} |
||||
|
||||
private void safeRelease(final Releasable releasable) { |
||||
if (releasable != null) { |
||||
releasable.release(); |
||||
} |
||||
} |
||||
|
||||
private NodeJS(final V8 v8) { |
||||
this.v8 = v8; |
||||
} |
||||
|
||||
private void init(final V8Function require) { |
||||
this.require = require; |
||||
} |
||||
|
||||
private static File createTemporaryScriptFile(final String script, final String name) throws IOException { |
||||
File tempFile = File.createTempFile(name, TMP_JS_EXT); |
||||
PrintWriter writer = new PrintWriter(tempFile, "UTF-8"); |
||||
try { |
||||
writer.print(script); |
||||
} finally { |
||||
writer.close(); |
||||
} |
||||
return tempFile; |
||||
} |
||||
} |
@ -1,12 +0,0 @@
|
||||
package com.eclipsesource.v8; |
||||
|
||||
public class Platform { |
||||
public static final String ANDROID = "android"; |
||||
public static final String LINUX = "linux"; |
||||
public static final String MACOSX = "macosx"; |
||||
public static final String WINDOWS = "windows"; |
||||
|
||||
public static final String NATIVE_CLIENT = "nacl"; |
||||
|
||||
public static final String UNKNOWN = "unknown"; |
||||
} |
@ -1,319 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2017 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* Trustin Lee - original OS/Arch/Vendor detection code (see: https://github.com/trustin/os-maven-plugin)
|
||||
* Wolfgang Steiner - initial API and implementation |
||||
* |
||||
* Copyright 2014 Trustin Heuiseung Lee. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.Closeable; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.util.Locale; |
||||
|
||||
public class PlatformDetector { |
||||
public static class Arch { |
||||
public static String getName() { |
||||
final String archProperty = System.getProperty("os.arch"); |
||||
final String archName = normalizeArch(archProperty); |
||||
|
||||
if (archName.equals(Platform.UNKNOWN)) { |
||||
throw new UnsatisfiedLinkError("Unsupported arch: " + archProperty); |
||||
} |
||||
|
||||
return archName; |
||||
} |
||||
} |
||||
|
||||
public static class OS { |
||||
public static String getName() { |
||||
final String osProperty = System.getProperty("os.name"); |
||||
final String osName = normalizeOs(osProperty); |
||||
|
||||
final String vendorProperty = System.getProperty("java.specification.vendor"); |
||||
final String vendorName = normalize(vendorProperty); |
||||
|
||||
// special handling for android
|
||||
if (vendorName.contains("android") || osName.contains("android")) { |
||||
return Platform.ANDROID; |
||||
} |
||||
|
||||
if (osName.equals(Platform.UNKNOWN)) { |
||||
throw new UnsatisfiedLinkError("Unsupported platform/vendor: " + osProperty + " / " + vendorProperty); |
||||
} |
||||
|
||||
return osName; |
||||
} |
||||
|
||||
public static boolean isWindows() { |
||||
return getName().equals(Platform.WINDOWS); |
||||
} |
||||
|
||||
public static boolean isMac() { |
||||
return getName().equals(Platform.MACOSX); |
||||
} |
||||
|
||||
public static boolean isLinux() { |
||||
return getName().equals(Platform.LINUX); |
||||
} |
||||
|
||||
public static boolean isNativeClient() { |
||||
return getName().equals(Platform.NATIVE_CLIENT); |
||||
} |
||||
|
||||
public static boolean isAndroid() { |
||||
return getName().equals(Platform.ANDROID); |
||||
} |
||||
|
||||
public static String getLibFileExtension() { |
||||
if (isWindows()) { |
||||
return "dll"; |
||||
} |
||||
|
||||
if (isMac()) { |
||||
return "dylib"; |
||||
} |
||||
|
||||
if (isLinux() |
||||
|| isAndroid() |
||||
|| isNativeClient()) { |
||||
return "so"; |
||||
} |
||||
|
||||
throw new UnsatisfiedLinkError("Unsupported platform library-extension for: " + getName()); |
||||
} |
||||
} |
||||
|
||||
public static class Vendor { |
||||
private static final String[] LINUX_OS_RELEASE_FILES = {"/etc/os-release", "/usr/lib/os-release"}; |
||||
private static final String REDHAT_RELEASE_FILE = "/etc/redhat-release"; |
||||
private static final String LINUX_ID_PREFIX = "ID="; |
||||
|
||||
public static String getName() { |
||||
if (OS.isWindows()) { |
||||
return "microsoft"; |
||||
} |
||||
if (OS.isMac()) { |
||||
return "apple"; |
||||
} |
||||
if (OS.isLinux()) { |
||||
return getLinuxOsReleaseId(); |
||||
} |
||||
if (OS.isAndroid()) { |
||||
return "google"; |
||||
} |
||||
//如果if条件全部不符合,就会陷入死循环,代码存在风险
|
||||
//throw new UnsatisfiedLinkError("Unsupported vendor: " + getName());
|
||||
return null; |
||||
} |
||||
|
||||
private static String getLinuxOsReleaseId() { |
||||
// First, look for the os-release file.
|
||||
for (String osReleaseFileName : LINUX_OS_RELEASE_FILES) { |
||||
File file = new File(osReleaseFileName); |
||||
if (file.exists()) { |
||||
return parseLinuxOsReleaseFile(file); |
||||
} |
||||
} |
||||
|
||||
// Older versions of redhat don't have /etc/os-release. In this case, try
|
||||
// parsing this file.
|
||||
File file = new File(REDHAT_RELEASE_FILE); |
||||
if (file.exists()) { |
||||
return parseLinuxRedhatReleaseFile(file); |
||||
} |
||||
|
||||
//linux系统下如果缺失/etc/os-release,/usr/lib/os-release,/etc/redhat-release三个文件,就会和getName方法就会一直互相调用
|
||||
//throw new UnsatisfiedLinkError("Unsupported linux vendor: " + getName());
|
||||
return null; |
||||
} |
||||
|
||||
private static String parseLinuxOsReleaseFile(final File file) { |
||||
BufferedReader reader = null; |
||||
try { |
||||
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); |
||||
|
||||
String id = null; |
||||
String line; |
||||
while((line = reader.readLine()) != null) { |
||||
// Parse the ID line.
|
||||
if (line.startsWith(LINUX_ID_PREFIX)) { |
||||
// Set the ID for this version.
|
||||
id = normalizeOsReleaseValue(line.substring(LINUX_ID_PREFIX.length())); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return id; |
||||
} catch (IOException ignored) { |
||||
// Just absorb. Don't treat failure to read /etc/os-release as an error.
|
||||
} finally { |
||||
closeQuietly(reader); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static String parseLinuxRedhatReleaseFile(final File file) { |
||||
BufferedReader reader = null; |
||||
try { |
||||
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); |
||||
|
||||
// There is only a single line in this file.
|
||||
String line = reader.readLine(); |
||||
if (line != null) { |
||||
line = line.toLowerCase(Locale.US); |
||||
|
||||
String id; |
||||
if (line.contains("centos")) { |
||||
id = "centos"; |
||||
} else if (line.contains("fedora")) { |
||||
id = "fedora"; |
||||
} else if (line.contains("red hat enterprise linux")) { |
||||
id = "rhel"; |
||||
} else { |
||||
// Other variants are not currently supported.
|
||||
return null; |
||||
} |
||||
|
||||
return id; |
||||
} |
||||
} catch (IOException ignored) { |
||||
// Just absorb. Don't treat failure to read /etc/os-release as an error.
|
||||
} finally { |
||||
closeQuietly(reader); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static void closeQuietly(final Closeable obj) { |
||||
try { |
||||
if (obj != null) { |
||||
obj.close(); |
||||
} |
||||
} catch (IOException ignored) { |
||||
// Ignore.
|
||||
} |
||||
} |
||||
} |
||||
|
||||
private static String normalizeOsReleaseValue(final String value) { |
||||
// Remove any quotes from the string.
|
||||
return value.trim().replace("\"", ""); |
||||
} |
||||
|
||||
private static String normalizeOs(String value) { |
||||
value = normalize(value); |
||||
if (value.startsWith("aix")) { |
||||
return "aix"; |
||||
} |
||||
if (value.startsWith("hpux")) { |
||||
return "hpux"; |
||||
} |
||||
if (value.startsWith("os400")) { |
||||
// Avoid the names such as os4000
|
||||
if ((value.length() <= 5) || !Character.isDigit(value.charAt(5))) { |
||||
return "os400"; |
||||
} |
||||
} |
||||
if (value.startsWith("android")) { |
||||
return Platform.ANDROID; |
||||
} |
||||
if (value.startsWith("linux")) { |
||||
return Platform.LINUX; |
||||
} |
||||
if (value.startsWith("nacl")) { |
||||
return Platform.NATIVE_CLIENT; |
||||
} |
||||
if (value.startsWith("macosx") || value.startsWith("osx")) { |
||||
return Platform.MACOSX; |
||||
} |
||||
if (value.startsWith("freebsd")) { |
||||
return "freebsd"; |
||||
} |
||||
if (value.startsWith("openbsd")) { |
||||
return "openbsd"; |
||||
} |
||||
if (value.startsWith("netbsd")) { |
||||
return "netbsd"; |
||||
} |
||||
if (value.startsWith("solaris") || value.startsWith("sunos")) { |
||||
return "sunos"; |
||||
} |
||||
if (value.startsWith("windows")) { |
||||
return Platform.WINDOWS; |
||||
} |
||||
|
||||
return Platform.UNKNOWN; |
||||
} |
||||
|
||||
private static String normalizeArch(String value) { |
||||
value = normalize(value); |
||||
if (value.matches("^(x8664|amd64|ia32e|em64t|x64)$")) { |
||||
return "x86_64"; |
||||
} |
||||
if (value.matches("^(x8632|x86|i[3-6]86|ia32|x32)$")) { |
||||
return "x86_32"; |
||||
} |
||||
if (value.matches("^(ia64|itanium64)$")) { |
||||
return "itanium_64"; |
||||
} |
||||
if (value.matches("^(sparc|sparc32)$")) { |
||||
return "sparc_32"; |
||||
} |
||||
if (value.matches("^(sparcv9|sparc64)$")) { |
||||
return "sparc_64"; |
||||
} |
||||
if (value.matches("^(arm|arm32)$") || value.startsWith("armv7")) { |
||||
return "arm_32"; |
||||
} |
||||
if ("aarch64".equals(value) || value.startsWith("armv8")) { |
||||
return "aarch_64"; |
||||
} |
||||
if (value.matches("^(ppc|ppc32)$")) { |
||||
return "ppc_32"; |
||||
} |
||||
if ("ppc64".equals(value)) { |
||||
return "ppc_64"; |
||||
} |
||||
if ("ppc64le".equals(value)) { |
||||
return "ppcle_64"; |
||||
} |
||||
if ("s390".equals(value)) { |
||||
return "s390_32"; |
||||
} |
||||
if ("s390x".equals(value)) { |
||||
return "s390_64"; |
||||
} |
||||
|
||||
return Platform.UNKNOWN; |
||||
} |
||||
|
||||
private static String normalize(final String value) { |
||||
if (value == null) { |
||||
return ""; |
||||
} |
||||
return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", ""); |
||||
} |
||||
} |
@ -1,34 +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; |
||||
|
||||
/** |
||||
* Callback used to track when native handles are created and released. |
||||
*/ |
||||
public interface ReferenceHandler { |
||||
|
||||
/** |
||||
* Called when a native handle is first created. The V8Value |
||||
* referenced by that handle is passed as a parameter. |
||||
* |
||||
* @param object The V8Value referenced by the handle |
||||
*/ |
||||
public void v8HandleCreated(V8Value object); |
||||
|
||||
/** |
||||
* Called when a native handle is released. The V8Value |
||||
* referenced by that handle is passed as a parameter. |
||||
* |
||||
* @param object The V8Value referenced by the handle |
||||
*/ |
||||
public void v8HandleDisposed(V8Value object); |
||||
|
||||
} |
@ -1,30 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
import java.io.Closeable; |
||||
|
||||
/** |
||||
* An interface used to denote all V8 Classes which can be released. |
||||
*/ |
||||
public interface Releasable extends Closeable { |
||||
|
||||
/** |
||||
* Release the underlying resources. Once an object is released |
||||
* it typically cannot be used again. |
||||
*/ |
||||
void close(); |
||||
|
||||
/** |
||||
* Synonym for {@link #close()}. |
||||
*/ |
||||
void release(); |
||||
} |
@ -1,5 +0,0 @@
|
||||
package com.eclipsesource.v8; |
||||
|
||||
public interface SignatureProvider { |
||||
public byte[] getSignature(String uri); |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,472 +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; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.nio.ByteOrder; |
||||
|
||||
/** |
||||
* V8ArrayBuffers represent ArrayBuffers from V8, but are backed by a |
||||
* java.nio.ByteBuffer. This means that any data stored in a TypedArray |
||||
* can be accessed by the java.nio.ByteBuffer. This significantly improves |
||||
* performance of data access from Java to JavaScript. |
||||
* |
||||
* V8ArrayBuffers can either be constructed in Java, or returned from |
||||
* JavaScript. |
||||
* |
||||
*/ |
||||
public class V8ArrayBuffer extends V8Value { |
||||
|
||||
ByteBuffer byteBuffer; |
||||
|
||||
/** |
||||
* Creates a new V8ArrayBuffer on a given V8Runtime with a |
||||
* given capacity. |
||||
* |
||||
* @param v8 The runtime on which to create the ArrayBuffer |
||||
* @param capacity The capacity of the buffer |
||||
*/ |
||||
public V8ArrayBuffer(final V8 v8, final int capacity) { |
||||
super(v8); |
||||
initialize(v8.getV8RuntimePtr(), capacity); |
||||
byteBuffer = v8.createV8ArrayBufferBackingStore(v8.getV8RuntimePtr(), objectHandle, capacity); |
||||
byteBuffer.order(ByteOrder.nativeOrder()); |
||||
} |
||||
|
||||
public V8ArrayBuffer(final V8 v8, ByteBuffer byteBuffer) { |
||||
super(v8); |
||||
if (byteBuffer == null) { |
||||
byteBuffer = ByteBuffer.allocateDirect(0); |
||||
} |
||||
if (!byteBuffer.isDirect()) { |
||||
throw new IllegalArgumentException("ByteBuffer must be a allocated as a direct ByteBuffer"); |
||||
} |
||||
initialize(v8.getV8RuntimePtr(), byteBuffer); |
||||
this.byteBuffer = byteBuffer; |
||||
byteBuffer.order(ByteOrder.nativeOrder()); |
||||
} |
||||
|
||||
@Override |
||||
protected void initialize(final long runtimePtr, final Object data) { |
||||
v8.checkThread(); |
||||
if (data instanceof ByteBuffer) { |
||||
ByteBuffer buffer = (ByteBuffer) data; |
||||
int capacity = buffer.limit(); |
||||
objectHandle = v8.initNewV8ArrayBuffer(v8.getV8RuntimePtr(), buffer, capacity); |
||||
} else { |
||||
int capacity = (Integer) data; |
||||
objectHandle = v8.initNewV8ArrayBuffer(v8.getV8RuntimePtr(), capacity); |
||||
} |
||||
released = false; |
||||
addObjectReference(objectHandle); |
||||
} |
||||
|
||||
@Override |
||||
protected V8Value createTwin() { |
||||
return new V8ArrayBuffer(v8, byteBuffer); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see com.eclipsesource.v8.V8Object#twin() |
||||
*/ |
||||
@Override |
||||
public V8ArrayBuffer twin() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return (V8ArrayBuffer) super.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the buffers limit |
||||
* |
||||
* @return the buffers limit |
||||
*/ |
||||
public int limit() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.limit(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the buffers capacity |
||||
* |
||||
* @return the buffers capacity |
||||
*/ |
||||
public final int capacity() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.capacity(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return |
||||
*/ |
||||
public final int position() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.position(); |
||||
} |
||||
|
||||
public final V8ArrayBuffer position(final int newPosition) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.position(newPosition); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer limit(final int newLimit) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.limit(newLimit); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer mark() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.mark(); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer reset() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.reset(); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer clear() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.clear(); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer flip() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.flip(); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer rewind() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.rewind(); |
||||
return this; |
||||
} |
||||
|
||||
public final int remaining() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.remaining(); |
||||
} |
||||
|
||||
public final boolean hasRemaining() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.hasRemaining(); |
||||
} |
||||
|
||||
public boolean isReadOnly() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.isReadOnly(); |
||||
} |
||||
|
||||
public byte get() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.get(); |
||||
} |
||||
|
||||
public V8ArrayBuffer put(final byte b) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.put(b); |
||||
return this; |
||||
} |
||||
|
||||
public byte get(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.get(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer put(final int index, final byte b) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.put(index, b); |
||||
return this; |
||||
} |
||||
|
||||
public V8ArrayBuffer get(final byte[] dst, final int offset, final int length) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.get(dst, offset, length); |
||||
return this; |
||||
} |
||||
|
||||
public V8ArrayBuffer get(final byte[] dst) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.get(dst); |
||||
return this; |
||||
} |
||||
|
||||
public V8ArrayBuffer put(final ByteBuffer src) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.put(src); |
||||
return this; |
||||
} |
||||
|
||||
public V8ArrayBuffer put(final byte[] src, final int offset, final int length) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.put(src, offset, length); |
||||
return this; |
||||
} |
||||
|
||||
public final V8ArrayBuffer put(final byte[] src) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.put(src); |
||||
return this; |
||||
} |
||||
|
||||
public final boolean hasArray() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.hasArray(); |
||||
} |
||||
|
||||
public final byte[] array() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.array(); |
||||
} |
||||
|
||||
public final int arrayOffset() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.arrayOffset(); |
||||
} |
||||
|
||||
public V8ArrayBuffer compact() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.compact(); |
||||
return this; |
||||
} |
||||
|
||||
public boolean isDirect() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.isDirect(); |
||||
} |
||||
|
||||
public final ByteOrder order() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.order(); |
||||
} |
||||
|
||||
public final V8ArrayBuffer order(final ByteOrder bo) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.order(bo); |
||||
return this; |
||||
} |
||||
|
||||
public char getChar() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getChar(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putChar(final char value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putChar(value); |
||||
return this; |
||||
} |
||||
|
||||
public char getChar(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getChar(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putChar(final int index, final char value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putChar(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public short getShort() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getShort(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putShort(final short value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putShort(value); |
||||
return this; |
||||
} |
||||
|
||||
public short getShort(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getShort(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putShort(final int index, final short value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putShort(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public int getInt() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getInt(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putInt(final int value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putInt(value); |
||||
return this; |
||||
} |
||||
|
||||
public int getInt(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getInt(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putInt(final int index, final int value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.asIntBuffer().put(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public long getLong() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getLong(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putLong(final long value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putLong(value); |
||||
return this; |
||||
} |
||||
|
||||
public long getLong(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getLong(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putLong(final int index, final long value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putLong(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public float getFloat() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getFloat(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putFloat(final float value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putFloat(value); |
||||
return this; |
||||
} |
||||
|
||||
public float getFloat(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getFloat(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putFloat(final int index, final float value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putFloat(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public double getDouble() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getDouble(); |
||||
} |
||||
|
||||
public V8ArrayBuffer putDouble(final double value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putDouble(value); |
||||
return this; |
||||
} |
||||
|
||||
public double getDouble(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.getDouble(index); |
||||
} |
||||
|
||||
public V8ArrayBuffer putDouble(final int index, final double value) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
byteBuffer.putDouble(index, value); |
||||
return this; |
||||
} |
||||
|
||||
public int floatLimit() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.asFloatBuffer().limit(); |
||||
} |
||||
|
||||
public int intLimit() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.asIntBuffer().limit(); |
||||
} |
||||
|
||||
public int shortLimit() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.asShortBuffer().limit(); |
||||
} |
||||
|
||||
public int doubleLimit() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return byteBuffer.asDoubleBuffer().limit(); |
||||
} |
||||
|
||||
} |
@ -1,98 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* A V8Value that represents a JavaScript function. |
||||
* JavaScript functions cannot be created in Java, but |
||||
* can be returned as the result of invoking a JS script |
||||
* or JS Function. |
||||
*/ |
||||
public class V8Function extends V8Object { |
||||
|
||||
/** |
||||
* Create a JavaScript function, that when invoked will call |
||||
* the javaCallback passed to the receiver. |
||||
* |
||||
* @param v8 The v8 runtime on which to create this function |
||||
* @param javaCallback The callback to invoke |
||||
*/ |
||||
public V8Function(final V8 v8, final JavaCallback javaCallback) { |
||||
super(v8, javaCallback); |
||||
} |
||||
|
||||
protected V8Function(final V8 v8) { |
||||
this(v8, null); |
||||
} |
||||
|
||||
@Override |
||||
protected V8Value createTwin() { |
||||
return new V8Function(v8); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see com.eclipsesource.v8.V8Object#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
if (released || v8.isReleased()) { |
||||
return "[Function released]"; |
||||
} |
||||
return super.toString(); |
||||
} |
||||
|
||||
@Override |
||||
protected void initialize(final long runtimePtr, final Object data) { |
||||
if (data == null) { |
||||
super.initialize(runtimePtr, null); |
||||
return; |
||||
} |
||||
JavaCallback javaCallback = (JavaCallback) data; |
||||
long[] pointers = v8.initNewV8Function(runtimePtr); |
||||
// position 0 is the object reference, position 1 is the function reference
|
||||
v8.createAndRegisterMethodDescriptor(javaCallback, pointers[1]); |
||||
released = false; |
||||
addObjectReference(pointers[0]); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see com.eclipsesource.v8.V8Object#twin() |
||||
*/ |
||||
@Override |
||||
public V8Function twin() { |
||||
return (V8Function) super.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Invoke the JavaScript function on the current runtime. |
||||
* |
||||
* @param receiver The object on which to call the function on. The |
||||
* receiver will be mapped to 'this' in JavaScript. If receiver is null |
||||
* or undefined, then the V8 runtime will be used instead. |
||||
* @param parameters The parameters passed to the JS Function. |
||||
* |
||||
* @return The result of JavaScript function. |
||||
*/ |
||||
@SuppressWarnings("resource") |
||||
public Object call(V8Object receiver, final V8Array parameters) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
v8.checkRuntime(receiver); |
||||
v8.checkRuntime(parameters); |
||||
receiver = receiver != null ? receiver : v8; |
||||
long parametersHandle = parameters == null ? 0 : parameters.getHandle(); |
||||
long receiverHandle = receiver.isUndefined() ? v8.getHandle() : receiver.getHandle(); |
||||
return v8.executeFunction(v8.getV8RuntimePtr(), receiverHandle, objectHandle, parametersHandle); |
||||
} |
||||
|
||||
} |
@ -1,113 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* Represents a lock for a V8Runtime that can be moved between |
||||
* threads. When instantiated, the lock is automatically assigned |
||||
* to the current thread. If another thread wishes to acquire the |
||||
* lock, it must first be released. |
||||
*/ |
||||
public class V8Locker { |
||||
|
||||
private Thread thread = null; |
||||
private boolean released = false; |
||||
private V8 runtime; |
||||
|
||||
V8Locker(final V8 runtime) { |
||||
this.runtime = runtime; |
||||
acquire(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the current thread associated with locker. |
||||
* |
||||
* @return The currently locked thread. |
||||
*/ |
||||
public Thread getThread() { |
||||
return thread; |
||||
} |
||||
|
||||
/** |
||||
* Acquire the lock if it's currently not acquired by another |
||||
* thread. If it's currently held by another thread, an |
||||
* Error will be thrown. |
||||
*/ |
||||
public synchronized void acquire() { |
||||
if ((thread != null) && (thread != Thread.currentThread())) { |
||||
throw new Error("Invalid V8 thread access: current thread is " + Thread.currentThread() + " while the locker has thread " + thread); |
||||
} else if ((thread == Thread.currentThread())) { |
||||
return; |
||||
} |
||||
runtime.acquireLock(runtime.getV8RuntimePtr()); |
||||
thread = Thread.currentThread(); |
||||
released = false; |
||||
} |
||||
|
||||
/** |
||||
* Acquire the lock if it's currently not acquired by another |
||||
* thread. If it's currently held by another thread, tryAcquire |
||||
* will return false, otherwise true is returned. |
||||
* |
||||
* @return Returns true if the lock was acquired, false otherwise. |
||||
*/ |
||||
public synchronized boolean tryAcquire() { |
||||
if ((thread != null) && (thread != Thread.currentThread())) { |
||||
return false; |
||||
} else if (thread == Thread.currentThread()) { |
||||
return true; |
||||
} |
||||
runtime.acquireLock(runtime.getV8RuntimePtr()); |
||||
thread = Thread.currentThread(); |
||||
released = false; |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Release the lock if it's currently held by the calling thread. |
||||
* If the current thread does not hold the lock, and error will be |
||||
* thrown. If no thread holds the lock then nothing will happen. |
||||
*/ |
||||
public synchronized void release() { |
||||
if ((released && (thread == null)) || runtime.isReleased()) { |
||||
return; |
||||
} |
||||
checkThread(); |
||||
runtime.releaseLock(runtime.getV8RuntimePtr()); |
||||
thread = null; |
||||
released = true; |
||||
} |
||||
|
||||
/** |
||||
* Checks if the locker has access to the current thread. |
||||
* If the locker holds a different thread, than an Error |
||||
* is thrown. |
||||
*/ |
||||
public void checkThread() { |
||||
if(released && (thread == null)){ |
||||
throw new Error("Invalid V8 thread access: the locker has been released!"); |
||||
} |
||||
if ((thread != Thread.currentThread())) { |
||||
throw new Error("Invalid V8 thread access: current thread is " + Thread.currentThread() + " while the locker has thread " + thread); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Check if the current thread holds this lock. |
||||
* |
||||
* @return Returns true if the current thread holds the lock, |
||||
* false otherwise. |
||||
*/ |
||||
public boolean hasLock() { |
||||
return thread == Thread.currentThread(); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* @author Bjorn |
||||
* @version 10.0 |
||||
* Created by Bjorn on 2020-11-26 |
||||
*/ |
||||
public class V8OutOfMemoryError extends V8RuntimeException { |
||||
|
||||
V8OutOfMemoryError(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
V8OutOfMemoryError() { |
||||
super(); |
||||
} |
||||
} |
@ -1,32 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* An exception that's used to indicate that method that should have returned a |
||||
* primitive, returned an Undefined instead. |
||||
* |
||||
* In Java, Undefined cannot be returned for all methods, especially if |
||||
* the method returns a primitive (int, double, boolean) or a String. |
||||
* In this case, if an Undefined should be returned from JS, then an instance |
||||
* of this exception is thrown. |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class V8ResultUndefined extends V8RuntimeException { |
||||
|
||||
V8ResultUndefined(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
V8ResultUndefined() { |
||||
super(); |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* A top-level exception used to indicate that a script failed. In most cases |
||||
* a more specific exception will be thrown. |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class V8RuntimeException extends RuntimeException { |
||||
|
||||
V8RuntimeException() { |
||||
} |
||||
|
||||
V8RuntimeException(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
} |
@ -1,24 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* An exception used to indicate that a script failed to compile. |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class V8ScriptCompilationException extends V8ScriptException { |
||||
|
||||
V8ScriptCompilationException(final String fileName, final int lineNumber, |
||||
final String message, final String sourceLine, final int startColumn, final int endColumn) { |
||||
super(fileName, lineNumber, message, sourceLine, startColumn, endColumn, null, null); |
||||
} |
||||
|
||||
} |
@ -1,165 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* An exception that indicates that the execution of a script failed. |
||||
* Details about the exception, such as the line number, stack trace, and |
||||
* message can retrieved using the accessors. |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public abstract class V8ScriptException extends V8RuntimeException { |
||||
|
||||
private final String fileName; |
||||
private final int lineNumber; |
||||
private final String jsMessage; |
||||
private final String sourceLine; |
||||
private final int startColumn; |
||||
private final int endColumn; |
||||
private final String jsStackTrace; |
||||
|
||||
V8ScriptException(final String fileName, |
||||
final int lineNumber, |
||||
final String jsMessage, |
||||
final String sourceLine, |
||||
final int startColumn, |
||||
final int endColumn, |
||||
final String jsStackTrace, |
||||
final Throwable cause) { |
||||
this.fileName = fileName; |
||||
this.lineNumber = lineNumber; |
||||
this.jsMessage = jsMessage; |
||||
this.sourceLine = sourceLine; |
||||
this.startColumn = startColumn; |
||||
this.endColumn = endColumn; |
||||
this.jsStackTrace = jsStackTrace; |
||||
if (cause != null) { |
||||
initCause(cause); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the JavaScript Stack as a String. |
||||
* |
||||
* @return The JavaScript stack. |
||||
*/ |
||||
public String getJSStackTrace() { |
||||
return jsStackTrace; |
||||
} |
||||
|
||||
/** |
||||
* Get the file name contains the script that was currently executing. |
||||
* |
||||
* @return The file name that contains the script. |
||||
*/ |
||||
public String getFileName() { |
||||
return fileName; |
||||
} |
||||
|
||||
/** |
||||
* Get the line number that the failure occurred on. |
||||
* |
||||
* @return The line number the failure occurred on. |
||||
*/ |
||||
public int getLineNumber() { |
||||
return lineNumber; |
||||
} |
||||
|
||||
/** |
||||
* Get the JavaScript column where the error begins. |
||||
* |
||||
* @return The JavaScript column where the error begins. |
||||
*/ |
||||
public int getStartColumn() { |
||||
return startColumn; |
||||
} |
||||
|
||||
/** |
||||
* Get the JavaScript column where the error ends. |
||||
* |
||||
* @return The JavaScript column where the error ends. |
||||
*/ |
||||
public int getEndColumn() { |
||||
return endColumn; |
||||
} |
||||
|
||||
/** |
||||
* Get the JavaScript line of source that caused the error. |
||||
* |
||||
* @return The JavaScript line of source that caused the error. |
||||
*/ |
||||
public String getSourceLine() { |
||||
return sourceLine; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
StringBuilder result = new StringBuilder(); |
||||
result.append(createMessageLine()); |
||||
result.append(createMessageDetails()); |
||||
result.append(createJSStackDetails()); |
||||
result.append("\n"); |
||||
result.append(this.getClass().getName()); |
||||
return result.toString(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.lang.Throwable#getMessage() |
||||
*/ |
||||
@Override |
||||
public String getMessage() { |
||||
return createMessageLine(); |
||||
} |
||||
|
||||
/** |
||||
* Get the message set by the JavaScript exception. |
||||
* |
||||
* @return The message set by the JavaScript exception. |
||||
*/ |
||||
public String getJSMessage() { |
||||
return jsMessage; |
||||
} |
||||
|
||||
private String createMessageLine() { |
||||
return fileName + ":" + lineNumber + ": " + jsMessage; |
||||
} |
||||
|
||||
private String createJSStackDetails() { |
||||
if (jsStackTrace != null) { |
||||
return "\n" + jsStackTrace; |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
private String createMessageDetails() { |
||||
StringBuilder result = new StringBuilder(); |
||||
if ((sourceLine != null) && !sourceLine.isEmpty()) { |
||||
result.append('\n'); |
||||
result.append(sourceLine); |
||||
result.append('\n'); |
||||
if (startColumn >= 0) { |
||||
result.append(createCharSequence(startColumn, ' ')); |
||||
result.append(createCharSequence(endColumn - startColumn, '^')); |
||||
} |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
private char[] createCharSequence(final int length, final char c) { |
||||
char[] result = new char[length]; |
||||
for (int i = 0; i < length; i++) { |
||||
result[i] = c; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
} |
@ -1,40 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* An exception used to indicate that a script failed to execute. |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class V8ScriptExecutionException extends V8ScriptException { |
||||
|
||||
V8ScriptExecutionException(final String fileName, |
||||
final int lineNumber, |
||||
final String message, |
||||
final String sourceLine, |
||||
final int startColumn, |
||||
final int endColumn, |
||||
final String jsStackTrace) { |
||||
this(fileName, lineNumber, message, sourceLine, startColumn, endColumn, jsStackTrace, null); |
||||
} |
||||
|
||||
V8ScriptExecutionException(final String fileName, |
||||
final int lineNumber, |
||||
final String message, |
||||
final String sourceLine, |
||||
final int startColumn, |
||||
final int endColumn, |
||||
final String jsStackTrace, |
||||
final Throwable cause) { |
||||
super(fileName, lineNumber, message, sourceLine, startColumn, endColumn, jsStackTrace, cause); |
||||
} |
||||
|
||||
} |
@ -1,183 +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; |
||||
|
||||
/** |
||||
* A representation of a JS TypedArray in Java. The typed array is simply a 'view' onto |
||||
* a back buffer. |
||||
*/ |
||||
public class V8TypedArray extends V8Array { |
||||
|
||||
/** |
||||
* Create a new TypedArray from a specified ArrayBuffer, type, offset and size. For |
||||
* example, a V8Int32Array is a typed array where each value is a 32-bit integer. The |
||||
* typed array is backed by the V8ArrayBuffer. |
||||
* |
||||
* @param v8 The V8Runtime on which to create this Int32Array |
||||
* @param type The type of Array to create. Currently Integer and Byte are supported. |
||||
* @param buffer The buffer used to back the typed array |
||||
* @param offset The offset into the buffer at which to start the the array |
||||
* @param size The size of the typed array |
||||
*/ |
||||
public V8TypedArray(final V8 v8, final V8ArrayBuffer buffer, final int type, final int offset, final int size) { |
||||
super(v8, new V8ArrayData(buffer, offset, size, type)); |
||||
} |
||||
|
||||
private V8TypedArray(final V8 v8) { |
||||
super(v8); |
||||
} |
||||
|
||||
@Override |
||||
protected V8Value createTwin() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return new V8TypedArray(v8); |
||||
} |
||||
|
||||
@Override |
||||
public Object get(final int index) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
int type = getType(); |
||||
switch (type) { |
||||
case FLOAT_32_ARRAY: |
||||
return ((Number) super.get(index)).floatValue(); |
||||
case FLOAT_64_ARRAY: |
||||
return super.get(index); |
||||
case INT_32_ARRAY: |
||||
return super.get(index); |
||||
case INT_16_ARRAY: |
||||
return ((Number) super.get(index)).shortValue(); |
||||
case INT_8_ARRAY: |
||||
return ((Number) super.get(index)).byteValue(); |
||||
case UNSIGNED_INT_16_ARRAY: |
||||
return 0xFFFF & (Integer) super.get(index); |
||||
case UNSIGNED_INT_32_ARRAY: |
||||
return 0x00000000FFFFFFFF & ((Number) super.get(index)).longValue(); |
||||
case UNSIGNED_INT_8_CLAMPED_ARRAY: |
||||
return (short) (0x00FF & ((Number) super.get(index)).byteValue()); |
||||
case UNSIGNED_INT_8_ARRAY: |
||||
return (short) (0x00FF & ((Number) super.get(index)).shortValue()); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Provide access to the underlying ByteBuffer used for this TypedArray. |
||||
* The V8ArrayBuffer must be released. |
||||
* |
||||
* @return The V8ArrayBuffer used to back this TypedArray. |
||||
*/ |
||||
public V8ArrayBuffer getBuffer() { |
||||
return (V8ArrayBuffer) get("buffer"); |
||||
} |
||||
|
||||
@Override |
||||
protected void initialize(final long runtimePtr, final Object data) { |
||||
v8.checkThread(); |
||||
if (data == null) { |
||||
super.initialize(runtimePtr, data); |
||||
return; |
||||
} |
||||
V8ArrayData arrayData = (V8ArrayData) data; |
||||
checkArrayProperties(arrayData); |
||||
long handle = createTypedArray(runtimePtr, arrayData); |
||||
released = false; |
||||
addObjectReference(handle); |
||||
} |
||||
|
||||
private long createTypedArray(final long runtimePtr, final V8ArrayData arrayData) { |
||||
switch (arrayData.type) { |
||||
case V8Value.FLOAT_32_ARRAY: |
||||
return v8.initNewV8Float32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.FLOAT_64_ARRAY: |
||||
return v8.initNewV8Float64Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.UNSIGNED_INT_32_ARRAY: |
||||
return v8.initNewV8UInt32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.INT_16_ARRAY: |
||||
return v8.initNewV8Int16Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.UNSIGNED_INT_16_ARRAY: |
||||
return v8.initNewV8UInt16Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.INTEGER: |
||||
return v8.initNewV8Int32Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.UNSIGNED_INT_8_ARRAY: |
||||
return v8.initNewV8UInt8Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.INT_8_ARRAY: |
||||
return v8.initNewV8Int8Array(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY: |
||||
return v8.initNewV8UInt8ClampedArray(runtimePtr, arrayData.buffer.objectHandle, arrayData.offset, arrayData.size); |
||||
default: |
||||
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentation(arrayData.type)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Computes the size of the structures required for each TypedArray variation. |
||||
* |
||||
* @param type The type of the TypeArray |
||||
* @return The size of the structures required |
||||
*/ |
||||
public static int getStructureSize(final int type) { |
||||
switch (type) { |
||||
case V8Value.FLOAT_64_ARRAY: |
||||
return 8; |
||||
case V8Value.INT_32_ARRAY: |
||||
case V8Value.UNSIGNED_INT_32_ARRAY: |
||||
case V8Value.FLOAT_32_ARRAY: |
||||
return 4; |
||||
case V8Value.UNSIGNED_INT_16_ARRAY: |
||||
case V8Value.INT_16_ARRAY: |
||||
return 2; |
||||
case V8Value.INT_8_ARRAY: |
||||
case V8Value.UNSIGNED_INT_8_ARRAY: |
||||
case V8Value.UNSIGNED_INT_8_CLAMPED_ARRAY: |
||||
return 1; |
||||
default: |
||||
throw new IllegalArgumentException("Cannot create a typed array of type " + V8Value.getStringRepresentation(type)); |
||||
} |
||||
} |
||||
|
||||
private void checkArrayProperties(final V8ArrayData arrayData) { |
||||
checkOffset(arrayData); |
||||
checkSize(arrayData); |
||||
} |
||||
|
||||
private void checkSize(final V8ArrayData arrayData) { |
||||
if (arrayData.size < 0) { |
||||
throw new IllegalStateException("RangeError: Invalid typed array length"); |
||||
} |
||||
int limit = (arrayData.size * getStructureSize(arrayData.type)) + arrayData.offset; |
||||
if (limit > arrayData.buffer.limit()) { |
||||
throw new IllegalStateException("RangeError: Invalid typed array length"); |
||||
} |
||||
} |
||||
|
||||
private void checkOffset(final V8ArrayData arrayData) { |
||||
if ((arrayData.offset % getStructureSize(arrayData.type)) != 0) { |
||||
throw new IllegalStateException("RangeError: Start offset of Int32Array must be a multiple of " + getStructureSize(arrayData.type)); |
||||
} |
||||
} |
||||
|
||||
private static class V8ArrayData { |
||||
private V8ArrayBuffer buffer; |
||||
private int offset; |
||||
private int size; |
||||
private int type; |
||||
|
||||
public V8ArrayData(final V8ArrayBuffer buffer, final int offset, final int size, final int type) { |
||||
this.buffer = buffer; |
||||
this.offset = offset; |
||||
this.size = size; |
||||
this.type = type; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,391 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8; |
||||
|
||||
/** |
||||
* A base class for all V8 resources. V8 resources must |
||||
* be closed/released. The rules for releasing resources is as |
||||
* follows: |
||||
* |
||||
* 1. If you created it, you must close it, with one exception; |
||||
* if the object is being passed pack via a return statement, |
||||
* the system will release it for you. |
||||
* |
||||
* 2. If the system created it, you don’t need to worry about it, |
||||
* with one caveat; if the object was returned to you as a |
||||
* result of a method call, you must close it. |
||||
*/ |
||||
abstract public class V8Value implements Releasable { |
||||
|
||||
public static final int NULL = 0; |
||||
public static final int UNKNOWN = 0; |
||||
public static final int INTEGER = 1; |
||||
public static final int INT_32_ARRAY = 1; |
||||
public static final int DOUBLE = 2; |
||||
public static final int FLOAT_64_ARRAY = 2; |
||||
public static final int BOOLEAN = 3; |
||||
public static final int STRING = 4; |
||||
public static final int V8_ARRAY = 5; |
||||
public static final int V8_OBJECT = 6; |
||||
public static final int V8_FUNCTION = 7; |
||||
public static final int V8_TYPED_ARRAY = 8; |
||||
public static final int BYTE = 9; |
||||
public static final int INT_8_ARRAY = 9; |
||||
public static final int V8_ARRAY_BUFFER = 10; |
||||
public static final int UNSIGNED_INT_8_ARRAY = 11; |
||||
public static final int UNSIGNED_INT_8_CLAMPED_ARRAY = 12; |
||||
public static final int INT_16_ARRAY = 13; |
||||
public static final int UNSIGNED_INT_16_ARRAY = 14; |
||||
public static final int UNSIGNED_INT_32_ARRAY = 15; |
||||
public static final int FLOAT_32_ARRAY = 16; |
||||
public static final int UNDEFINED = 99; |
||||
|
||||
protected V8 v8; |
||||
protected long objectHandle; |
||||
protected boolean released = true; |
||||
|
||||
protected V8Value() { |
||||
super(); |
||||
} |
||||
|
||||
protected V8Value(final V8 v8) { |
||||
if (v8 == null) { |
||||
this.v8 = (V8) this; |
||||
} else { |
||||
this.v8 = v8; |
||||
} |
||||
} |
||||
|
||||
protected void initialize(final long runtimePtr, final Object data) { |
||||
long objectHandle = v8.initNewV8Object(runtimePtr); |
||||
released = false; |
||||
addObjectReference(objectHandle); |
||||
} |
||||
|
||||
protected void addObjectReference(final long objectHandle) throws Error { |
||||
this.objectHandle = objectHandle; |
||||
try { |
||||
v8.addObjRef(this); |
||||
} catch (Error e) { |
||||
release(); |
||||
throw e; |
||||
} catch (RuntimeException e) { |
||||
release(); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a string representation of the V8 Type. |
||||
* @param type Type to return as a string. See constants in V8Value. |
||||
* @return The V8Value type as a string. |
||||
* @deprecated Use |
||||
*/ |
||||
@Deprecated |
||||
public static String getStringRepresentaion(final int type) { |
||||
return getStringRepresentation(type); |
||||
} |
||||
|
||||
/** |
||||
* Returns a string representation of the V8 Type. |
||||
* @param type Type to return as a string. See constants in V8Value. |
||||
* @return The V8Value type as a string. |
||||
*/ |
||||
public static String getStringRepresentation(final int type) { |
||||
switch (type) { |
||||
case NULL: |
||||
return "Null"; |
||||
case INTEGER: |
||||
return "Integer"; |
||||
case DOUBLE: |
||||
return "Double"; |
||||
case BOOLEAN: |
||||
return "Boolean"; |
||||
case STRING: |
||||
return "String"; |
||||
case V8_ARRAY: |
||||
return "V8Array"; |
||||
case V8_OBJECT: |
||||
return "V8Object"; |
||||
case V8_FUNCTION: |
||||
return "V8Function"; |
||||
case V8_TYPED_ARRAY: |
||||
return "V8TypedArray"; |
||||
case BYTE: |
||||
return "Byte"; |
||||
case V8_ARRAY_BUFFER: |
||||
return "V8ArrayBuffer"; |
||||
case UNSIGNED_INT_8_ARRAY: |
||||
return "UInt8Array"; |
||||
case UNSIGNED_INT_8_CLAMPED_ARRAY: |
||||
return "UInt8ClampedArray"; |
||||
case INT_16_ARRAY: |
||||
return "Int16Array"; |
||||
case UNSIGNED_INT_16_ARRAY: |
||||
return "UInt16Array"; |
||||
case UNSIGNED_INT_32_ARRAY: |
||||
return "UInt32Array"; |
||||
case FLOAT_32_ARRAY: |
||||
return "Float32Array"; |
||||
case UNDEFINED: |
||||
return "Undefined"; |
||||
default: |
||||
throw new IllegalArgumentException("Invalid V8 type: " + type); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns a constructor name of the V8 Value. |
||||
* |
||||
* @return The V8Value constructor name as a string. |
||||
*/ |
||||
public String getConstructorName() { |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
return v8.getConstructorName(v8.getV8RuntimePtr(), objectHandle); |
||||
} |
||||
|
||||
/** |
||||
* Determines if this value is undefined. |
||||
* |
||||
* @return Returns true if the value is undefined, false otherwise |
||||
*/ |
||||
public boolean isUndefined() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Gets the runtime this Value was created on. |
||||
* |
||||
* @return Returns the V8 runtime this value is associated with. |
||||
*/ |
||||
public V8 getRuntime() { |
||||
return v8; |
||||
} |
||||
|
||||
/** |
||||
* Returns the 'type' of this V8Value. The available types are defined |
||||
* as constants in {@link V8Value}. Only types that inherit from |
||||
* {@link V8Value} can be returned here. |
||||
* |
||||
* @return The 'type of this V8Value. |
||||
*/ |
||||
public int getV8Type() { |
||||
if (isUndefined()) { |
||||
return UNDEFINED; |
||||
} |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
return v8.getType(v8.getV8RuntimePtr(), objectHandle); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new Java object pointing at the same V8 Value |
||||
* as this. If the value is mutated (by adding new members or |
||||
* changing existing ones) then both the original and twin |
||||
* will be updated. Twins are .equal and .strict equals, but |
||||
* not == in Java. |
||||
* |
||||
* Twins must be closed separately since they have their own |
||||
* native resources. |
||||
* |
||||
* @return A new Java object pointing at the same V8 Value |
||||
* as this. |
||||
*/ |
||||
public V8Value twin() { |
||||
if (isUndefined()) { |
||||
return this; |
||||
} |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
V8Value twin = createTwin(); |
||||
v8.createTwin(this, twin); |
||||
return twin; |
||||
} |
||||
|
||||
/** |
||||
* Sets the V8Value as weak reference. A weak reference will eventually |
||||
* be closed when no more references exist to this object. Once setWeak |
||||
* is called, you should check if {@link V8Value#isReleased()} is true |
||||
* before invoking any methods on this object. |
||||
* |
||||
* If any other references exist to this object, the object will not be |
||||
* reclaimed. Even if no reference exist, V8 does not give any guarantee |
||||
* the object will be closed, so this should only be used if there is no |
||||
* other way to track object usage. |
||||
* |
||||
* @return The receiver. |
||||
*/ |
||||
public V8Value setWeak() { |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
v8.v8WeakReferences.put(getHandle(), this); |
||||
v8.setWeak(v8.getV8RuntimePtr(), getHandle()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Clears any weak reference set on this V8Value and makes this a strong |
||||
* reference. Strong references will not be garbage collected and this |
||||
* Object must be explicitly released. |
||||
* |
||||
* Calling clearWeak does nothing if the object is not currently set |
||||
* to weak. |
||||
* |
||||
* @return The receiver. |
||||
*/ |
||||
public V8Value clearWeak() { |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
v8.v8WeakReferences.remove(getHandle()); |
||||
v8.clearWeak(v8.getV8RuntimePtr(), getHandle()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* If {@link V8Value#setWeak()} has been called on this Object, this method |
||||
* will return true. Otherwise it will return false. |
||||
* |
||||
* @return Returns true if this object has been set 'Weak', return false otherwise. |
||||
*/ |
||||
public boolean isWeak() { |
||||
v8.checkThread(); |
||||
v8.checkReleased(); |
||||
return v8.isWeak(v8.getV8RuntimePtr(), getHandle()); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.io.Closeable#close() |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
v8.checkThread(); |
||||
if (!released) { |
||||
try { |
||||
v8.releaseObjRef(this); |
||||
} finally { |
||||
released = true; |
||||
v8.release(v8.getV8RuntimePtr(), objectHandle); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Releases the native resources associated with this V8Value. |
||||
* |
||||
* @deprecated use close() instead. |
||||
*/ |
||||
@Override |
||||
@Deprecated |
||||
public void release() { |
||||
close(); |
||||
} |
||||
|
||||
/** |
||||
* Determine if the native resources have been released. Once released |
||||
* a V8 Value can no longer be used. |
||||
* |
||||
* @return Returns true if this object has been released, false otherwise. |
||||
*/ |
||||
public boolean isReleased() { |
||||
return released; |
||||
} |
||||
|
||||
/** |
||||
* Performs a JS === on the parameter and the receiver. |
||||
* |
||||
* @param that The Object to compare this object against. |
||||
* @return Returns true iff this === that |
||||
*/ |
||||
public boolean strictEquals(final Object that) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
if (that == this) { |
||||
return true; |
||||
} |
||||
if (that == null) { |
||||
return false; |
||||
} |
||||
if (!(that instanceof V8Value)) { |
||||
return false; |
||||
} |
||||
if (isUndefined() && ((V8Value) that).isUndefined()) { |
||||
return true; |
||||
} |
||||
if (((V8Value) that).isUndefined()) { |
||||
return false; |
||||
} |
||||
return v8.strictEquals(v8.getV8RuntimePtr(), getHandle(), ((V8Value) that).getHandle()); |
||||
} |
||||
|
||||
protected long getHandle() { |
||||
checkReleased(); |
||||
return objectHandle; |
||||
} |
||||
|
||||
protected abstract V8Value createTwin(); |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.lang.Object#equals(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public boolean equals(final Object that) { |
||||
return strictEquals(that); |
||||
} |
||||
|
||||
/** |
||||
* Performs a JS == on the parameter and the receiver. |
||||
* |
||||
* @param that The Object to compare this object against. |
||||
* @return Returns true iff this == that |
||||
*/ |
||||
public boolean jsEquals(final Object that) { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
if (that == this) { |
||||
return true; |
||||
} |
||||
if (that == null) { |
||||
return false; |
||||
} |
||||
if (!(that instanceof V8Value)) { |
||||
return false; |
||||
} |
||||
if (isUndefined() && ((V8Value) that).isUndefined()) { |
||||
return true; |
||||
} |
||||
if (((V8Value) that).isUndefined()) { |
||||
return false; |
||||
} |
||||
return v8.equals(v8.getV8RuntimePtr(), getHandle(), ((V8Value) that).getHandle()); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.lang.Object#hashCode() |
||||
*/ |
||||
@Override |
||||
public int hashCode() { |
||||
v8.checkThread(); |
||||
checkReleased(); |
||||
return v8.identityHash(v8.getV8RuntimePtr(), getHandle()); |
||||
} |
||||
|
||||
protected void checkReleased() { |
||||
if (released) { |
||||
throw new IllegalStateException("Object released"); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,55 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Holds information about break events. |
||||
*/ |
||||
public class BreakEvent extends EventData { |
||||
|
||||
private static final String SOURCE_LINE_TEXT = "sourceLineText"; |
||||
private static final String SOURCE_COLUMN = "sourceColumn"; |
||||
private static final String SOURCE_LINE = "sourceLine"; |
||||
|
||||
BreakEvent(final V8Object eventData) { |
||||
super(eventData); |
||||
} |
||||
|
||||
/** |
||||
* Returns the source line that this break event occurred on. |
||||
* |
||||
* @return The line number that this break event occurred on. |
||||
*/ |
||||
public int getSourceLine() { |
||||
return v8Object.executeIntegerFunction(SOURCE_LINE, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the source column that this break event occurred on. |
||||
* |
||||
* @return The column number that this break event occurred on. |
||||
*/ |
||||
public int getSourceColumn() { |
||||
return v8Object.executeIntegerFunction(SOURCE_COLUMN, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the text of the line that this event occurred on. |
||||
* |
||||
* @return The text of the line that this event occurred on. |
||||
*/ |
||||
public String getSourceLineText() { |
||||
return v8Object.executeStringFunction(SOURCE_LINE_TEXT, null); |
||||
} |
||||
|
||||
} |
@ -1,20 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.debug.DebugHandler.DebugEvent; |
||||
|
||||
public interface BreakHandler { |
||||
|
||||
public void onBreak(DebugEvent type, ExecutionState state, EventData eventData, V8Object data); |
||||
|
||||
} |
@ -1,24 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Holds information about Compile Events. |
||||
*/ |
||||
public class CompileEvent extends EventData { |
||||
|
||||
CompileEvent(final V8Object eventData) { |
||||
super(eventData); |
||||
} |
||||
|
||||
} |
@ -1,363 +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.debug; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import com.eclipsesource.v8.JavaVoidCallback; |
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Function; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* The entry point for the Debug API. The debug API is a Java API |
||||
* that exposes V8's JavaScript API. |
||||
* |
||||
* The API requires that V8 be initialized with the runtime flag |
||||
* '--expose-debug-as=__j2v8_debug_handler'. |
||||
*/ |
||||
public class DebugHandler implements Releasable { |
||||
|
||||
public static enum DebugEvent { |
||||
Undefined(0), Break(1), Exception(2), NewFunction(3), BeforeCompile(4), AfterCompile(5), CompileError(6), PromiseError(7), AsyncTaskEvent(8); |
||||
int index; |
||||
|
||||
DebugEvent(final int index) { |
||||
this.index = index; |
||||
} |
||||
} |
||||
|
||||
public static String DEBUG_OBJECT_NAME = "__j2v8_Debug"; |
||||
|
||||
private static final String DEBUG_BREAK_HANDLER = "__j2v8_debug_handler"; |
||||
private static final String SET_SCRIPT_BREAK_POINT_BY_NAME = "setScriptBreakPointByName"; |
||||
private static final String SET_BREAK_POINT = "setBreakPoint"; |
||||
private static final String SET_LISTENER = "setListener"; |
||||
private static final String V8_DEBUG_OBJECT = "Debug"; |
||||
private static final String DISABLE_SCRIPT_BREAK_POINT = "disableScriptBreakPoint"; |
||||
private static final String ENABLE_SCRIPT_BREAK_POINT = "enableScriptBreakPoint"; |
||||
private static final String CLEAR_BREAK_POINT = "clearBreakPoint"; |
||||
private static final String DISABLE_ALL_BREAK_POINTS = "disableAllBreakPoints"; |
||||
private static final String SCRIPT_BREAK_POINTS = "scriptBreakPoints"; |
||||
private static final String FIND_SCRIPT_BREAK_POINT = "findScriptBreakPoint"; |
||||
private static final String NUMBER = "number"; |
||||
private static final String CHANGE_BREAK_POINT_CONDITION = "changeBreakPointCondition"; |
||||
|
||||
private V8 runtime; |
||||
private V8Object debugObject; |
||||
private List<BreakHandler> breakHandlers = new ArrayList<BreakHandler>(); |
||||
|
||||
/** |
||||
* Creates the Debug Handler for a particular V8 runtime. |
||||
* Before the runtime was created, V8.setFlags("expose-debug-as=__j2v8_debug_handler"); |
||||
* must be called. |
||||
* |
||||
* @param runtime The runtime on which to create the Debug Handler. |
||||
*/ |
||||
public DebugHandler(final V8 runtime) { |
||||
this.runtime = runtime; |
||||
setupDebugObject(runtime); |
||||
setupBreakpointHandler(); |
||||
} |
||||
|
||||
/** |
||||
* Adds a handler to be notified when a breakpoint is hit. |
||||
* |
||||
* @param handler The handler to notify. |
||||
*/ |
||||
public void addBreakHandler(final BreakHandler handler) { |
||||
runtime.getLocker().checkThread(); |
||||
breakHandlers.add(handler); |
||||
} |
||||
|
||||
/** |
||||
* Removes a handler from the list of breakpoint handlers. |
||||
* If the handler is not present in the list, the list is unchanged. |
||||
* |
||||
* @param handler The handler to remove. |
||||
*/ |
||||
public void removeBreakHandler(final BreakHandler handler) { |
||||
runtime.getLocker().checkThread(); |
||||
breakHandlers.remove(handler); |
||||
} |
||||
|
||||
/** |
||||
* Registers a function breakpoint. When the JavaScript function |
||||
* is invoked, the breakpoint will be 'hit'. |
||||
* |
||||
* @param function The function on which to register the breakpoint. |
||||
* @return The berakpointID. |
||||
*/ |
||||
public int setBreakpoint(final V8Function function) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(function); |
||||
try { |
||||
return debugObject.executeIntegerFunction(SET_BREAK_POINT, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Registers a breakpoint given a scriptID and line number. The breakpoint |
||||
* will be 'hit' when the script is executed and the given line is reached. |
||||
* |
||||
* @param scriptID The ID of the script on which to set the breakpoint. |
||||
* @param lineNumber The line number on which to set the breakpoint. |
||||
* @return The berakpointID. |
||||
*/ |
||||
public int setScriptBreakpoint(final String scriptID, final int lineNumber) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(scriptID); |
||||
parameters.push(lineNumber); |
||||
try { |
||||
return debugObject.executeIntegerFunction(SET_SCRIPT_BREAK_POINT_BY_NAME, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Enables a breakpoint. |
||||
* |
||||
* @param breakpointID The breakpoint to enable. |
||||
*/ |
||||
public void enableScriptBreakPoint(final int breakpointID) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(breakpointID); |
||||
try { |
||||
debugObject.executeVoidFunction(ENABLE_SCRIPT_BREAK_POINT, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Disables a breakpoint. |
||||
* |
||||
* @param breakpointID The breakpoint to disable |
||||
*/ |
||||
public void disableScriptBreakPoint(final int breakpointID) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(breakpointID); |
||||
try { |
||||
debugObject.executeVoidFunction(DISABLE_SCRIPT_BREAK_POINT, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Removes a Breakpoint. |
||||
* |
||||
* @param breakpointID The ID of the breakpoint to remove. |
||||
*/ |
||||
public void clearBreakPoint(final int breakpointID) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(breakpointID); |
||||
try { |
||||
debugObject.executeVoidFunction(CLEAR_BREAK_POINT, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Disables all breakpoints. |
||||
*/ |
||||
public void disableAllBreakPoints() { |
||||
debugObject.executeVoidFunction(DISABLE_ALL_BREAK_POINTS, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns a count of all the breakpoints |
||||
* |
||||
* @return A V8Array of Breakpoints. |
||||
*/ |
||||
public int getScriptBreakPointCount() { |
||||
V8Array breakPoints = debugObject.executeArrayFunction(SCRIPT_BREAK_POINTS, null); |
||||
try { |
||||
return breakPoints.length(); |
||||
} finally { |
||||
breakPoints.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get all the BreakPoint IDs as an array. |
||||
* |
||||
* @return A list of BreakPoint IDs. |
||||
*/ |
||||
public int[] getScriptBreakPointIDs() { |
||||
V8Array breakPoints = debugObject.executeArrayFunction(SCRIPT_BREAK_POINTS, null); |
||||
try { |
||||
int[] result = new int[breakPoints.length()]; |
||||
for (int i = 0; i < breakPoints.length(); i++) { |
||||
V8Object breakPoint = breakPoints.getObject(i); |
||||
try { |
||||
result[i] = breakPoint.executeIntegerFunction(NUMBER, null); |
||||
} finally { |
||||
breakPoint.close(); |
||||
} |
||||
} |
||||
return result; |
||||
} finally { |
||||
breakPoints.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the BreakPoint as referenced by the given ID. |
||||
* |
||||
* @param breakPointID The BreakPoint ID. |
||||
* @return The BreakPoint as referenced by the given ID. |
||||
*/ |
||||
public ScriptBreakPoint getScriptBreakPoint(final int breakPointID) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(breakPointID); |
||||
parameters.push(false); |
||||
V8Object scriptBreakPoint = null; |
||||
try { |
||||
scriptBreakPoint = debugObject.executeObjectFunction(FIND_SCRIPT_BREAK_POINT, parameters); |
||||
return new ScriptBreakPoint(scriptBreakPoint); |
||||
} finally { |
||||
parameters.close(); |
||||
if (scriptBreakPoint != null) { |
||||
scriptBreakPoint.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Changes the current condition on the breakpoint as specified by the breakpoint ID |
||||
* |
||||
* @param breakpointID The ID of the breakpoint of which to change the condition on |
||||
* @param condition The new condition to set |
||||
*/ |
||||
public void changeBreakPointCondition(final int breakpointID, final String condition) { |
||||
V8Array parameters = new V8Array(runtime); |
||||
parameters.push(breakpointID); |
||||
parameters.push(condition); |
||||
try { |
||||
debugObject.executeVoidFunction(CHANGE_BREAK_POINT_CONDITION, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.io.Closeable#close() |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
debugObject.close(); |
||||
} |
||||
|
||||
@Override |
||||
@Deprecated |
||||
public void release() { |
||||
close(); |
||||
} |
||||
|
||||
private void setupDebugObject(final V8 runtime) { |
||||
V8Object outerDebug = runtime.getObject(DEBUG_OBJECT_NAME); |
||||
try { |
||||
debugObject = outerDebug.getObject(V8_DEBUG_OBJECT); |
||||
} finally { |
||||
outerDebug.close(); |
||||
} |
||||
} |
||||
|
||||
private void setupBreakpointHandler() { |
||||
BreakpointHandler handler = new BreakpointHandler(); |
||||
debugObject.registerJavaMethod(handler, DEBUG_BREAK_HANDLER); |
||||
V8Function debugHandler = null; |
||||
V8Array parameters = null; |
||||
try { |
||||
debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER); |
||||
parameters = new V8Array(runtime); |
||||
parameters.push(debugHandler); |
||||
debugObject.executeFunction(SET_LISTENER, parameters); |
||||
} finally { |
||||
if ((debugHandler != null) && !debugHandler.isReleased()) { |
||||
debugHandler.close(); |
||||
} |
||||
if ((parameters != null) && !parameters.isReleased()) { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private class BreakpointHandler implements JavaVoidCallback { |
||||
|
||||
@Override |
||||
public void invoke(final V8Object receiver, final V8Array parameters) { |
||||
if ((parameters == null) || parameters.isUndefined()) { |
||||
return; |
||||
} |
||||
int event = parameters.getInteger(0); |
||||
for (BreakHandler handler : breakHandlers) { |
||||
invokeHandler(parameters, event, handler); |
||||
} |
||||
} |
||||
|
||||
private void invokeHandler(final V8Array parameters, final int event, final BreakHandler handler) { |
||||
V8Object execState = null; |
||||
V8Object eventData = null; |
||||
V8Object data = null; |
||||
ExecutionState state = null; |
||||
EventData typedEventData = null; |
||||
try { |
||||
execState = parameters.getObject(1); |
||||
eventData = parameters.getObject(2); |
||||
data = parameters.getObject(3); |
||||
state = new ExecutionState(execState); |
||||
DebugEvent type = DebugEvent.values()[event]; |
||||
typedEventData = createDebugEvent(type, eventData); |
||||
handler.onBreak(type, state, typedEventData, data); |
||||
} finally { |
||||
safeRelease(execState); |
||||
safeRelease(eventData); |
||||
safeRelease(data); |
||||
safeRelease(state); |
||||
safeRelease(typedEventData); |
||||
} |
||||
} |
||||
|
||||
private EventData createDebugEvent(final DebugEvent type, final V8Object eventData) { |
||||
switch (type) { |
||||
case Break: |
||||
return new BreakEvent(eventData); |
||||
case BeforeCompile: |
||||
return new CompileEvent(eventData); |
||||
case AfterCompile: |
||||
return new CompileEvent(eventData); |
||||
case Exception: |
||||
return new ExceptionEvent(eventData); |
||||
default: |
||||
break; |
||||
} |
||||
return new EventData(eventData); |
||||
} |
||||
|
||||
private void safeRelease(final Releasable object) { |
||||
if ((object != null)) { |
||||
object.release(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -1,40 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Typed information about different debug events. |
||||
*/ |
||||
public class EventData implements Releasable { |
||||
|
||||
protected V8Object v8Object; |
||||
|
||||
EventData(final V8Object eventData) { |
||||
v8Object = eventData.twin(); |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
if (!v8Object.isReleased()) { |
||||
v8Object.close(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
@Deprecated |
||||
public void release() { |
||||
close(); |
||||
} |
||||
|
||||
} |
@ -1,24 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Holds information about Exception Events. |
||||
*/ |
||||
public class ExceptionEvent extends EventData { |
||||
|
||||
ExceptionEvent(final V8Object eventData) { |
||||
super(eventData); |
||||
} |
||||
|
||||
} |
@ -1,100 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.debug.mirror.Frame; |
||||
|
||||
/** |
||||
* Represents the current execution state at a break. |
||||
* The execution state provides methods for inspecting |
||||
* the stack, variables and scopes. |
||||
* |
||||
* The ExecutionState should not be persisted as it |
||||
* will be released when the debugger continues. |
||||
* |
||||
*/ |
||||
public class ExecutionState implements Releasable { |
||||
|
||||
private static final String FRAME = "frame"; |
||||
private static final String PREPARE_STEP = "prepareStep"; |
||||
private static final String FRAME_COUNT = "frameCount"; |
||||
|
||||
private V8Object v8Object; |
||||
|
||||
ExecutionState(final V8Object v8Object) { |
||||
this.v8Object = v8Object.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the current stack frame count. |
||||
* |
||||
* @return The stack frame count. |
||||
*/ |
||||
public int getFrameCount() { |
||||
return v8Object.executeIntegerFunction(FRAME_COUNT, null); |
||||
} |
||||
|
||||
/** |
||||
* Indicates to the debugger how to proceed. If not called, |
||||
* the debugger will continue running until the next breakpoint |
||||
* is hit. |
||||
* |
||||
* @param action The step action to use. |
||||
*/ |
||||
public void prepareStep(final StepAction action) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(action.index); |
||||
try { |
||||
v8Object.executeVoidFunction(PREPARE_STEP, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the Frame at a given index |
||||
* |
||||
* @param index The stack index |
||||
* @return The stack frame at a given index |
||||
*/ |
||||
public Frame getFrame(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
V8Object frame = null; |
||||
try { |
||||
frame = v8Object.executeObjectFunction(FRAME, parameters); |
||||
return new Frame(frame); |
||||
} finally { |
||||
parameters.close(); |
||||
if (frame != null) { |
||||
frame.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
if ((v8Object != null) && !v8Object.isReleased()) { |
||||
v8Object.close(); |
||||
v8Object = null; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
@Deprecated |
||||
public void release() { |
||||
close(); |
||||
} |
||||
|
||||
} |
@ -1,94 +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.debug; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.V8ResultUndefined; |
||||
|
||||
/** |
||||
* Represents a BreakPoint. |
||||
*/ |
||||
public class ScriptBreakPoint implements Releasable { |
||||
|
||||
private static final String CONDITION = "condition"; |
||||
private static final String LINE = "line"; |
||||
private static final String NUMBER = "number"; |
||||
private static final String SET_CONDITION = "setCondition"; |
||||
|
||||
private V8Object v8Object; |
||||
|
||||
ScriptBreakPoint(final V8Object v8Object) { |
||||
this.v8Object = v8Object.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the ID of this breakpoint. |
||||
* |
||||
* @return The ID (breakpoint number) of this breakpoint. |
||||
*/ |
||||
public int getBreakPointNumber() { |
||||
return v8Object.executeIntegerFunction(NUMBER, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the line number of this breakpoint. |
||||
* |
||||
* @return The line number of this breakpoint. |
||||
*/ |
||||
public int getLine() { |
||||
return v8Object.executeIntegerFunction(LINE, null); |
||||
} |
||||
|
||||
/** |
||||
* Sets a condition to be evaluated before determining if |
||||
* the breakpoint event should be fired. |
||||
* |
||||
* @param condition A JavaScript condition to be evaluated. |
||||
*/ |
||||
public void setCondition(final String condition) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(condition); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_CONDITION, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the condition set on this breakpoint or the String |
||||
* 'undefined' if a condition was not set. |
||||
* |
||||
* @return The condition set on this breakpoint. |
||||
*/ |
||||
public String getCondition() { |
||||
try { |
||||
return v8Object.executeStringFunction(CONDITION, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return "undefined"; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
if ((v8Object != null) && !v8Object.isReleased()) { |
||||
v8Object.close(); |
||||
v8Object = null; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void release() { |
||||
close(); |
||||
} |
||||
} |
@ -1,25 +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.debug; |
||||
|
||||
/** |
||||
* An enumeration of possible Step Actions. A step action indicates to the |
||||
* debugger how to proceed with the next step. |
||||
*/ |
||||
public enum StepAction { |
||||
STEP_OUT(0), STEP_NEXT(1), STEP_IN(2), STEP_FRAME(3); |
||||
int index; |
||||
|
||||
StepAction(final int index) { |
||||
this.index = index; |
||||
} |
||||
|
||||
} |
@ -1,693 +0,0 @@
|
||||
/** |
||||
* Copyright 2016, Genuitec, LLC |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* Genuitec LLC - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.debug; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.net.ServerSocket; |
||||
import java.net.Socket; |
||||
import java.nio.charset.Charset; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
|
||||
import com.eclipsesource.v8.JavaVoidCallback; |
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Function; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* <p>V8DebugServer enables debuggers to connect to J2V8 via V8 server sockets debug protocol. |
||||
* Server has to be created in the same thread as the provided V8 runtime has been created (the V8 thread). |
||||
* You can specify port and whether the {@link #start()} method should |
||||
* block until a client connects. {@link #setTraceCommunication(boolean)} allows to output |
||||
* communication details for debugging purposes. Before creating V8 runtime you need to set V8 flag to expose |
||||
* debug object. If you do not intend to set other flags, than you can use {@link #configureV8ForDebugging()} |
||||
* method, otherwise set {@code -expose-debug-as=__j2v8_Debug} flag through {@link V8#setFlags(String)}. |
||||
* |
||||
* <p>Client connection is handled in a separate thread, however, commands are processed in the V8 thread. |
||||
* Therefore it is vital to provide an opportunity to process requests by calling |
||||
* {@link #processRequests(long)} method from the V8 thread. This will for instance |
||||
* allow to install breakpoints before the JavaScript code starts to execute. It is also good to call that |
||||
* method when V8 thread is idle to promptly provide responses to the debugger to avoid timeouts. |
||||
* |
||||
* <p>Example code: |
||||
* |
||||
* <code><br> |
||||
* //configure for debugging before creating runtime<br>
|
||||
* V8DebugServer.configureV8ForDebugging();<br> |
||||
* <br> |
||||
* //create V8 runtime<br>
|
||||
* V8 runtime = V8.createV8Runtime();<br> |
||||
* <br> |
||||
* //create and start debug server<br>
|
||||
* int port = 0;<br> |
||||
* boolean waitForConnection = true;<br> |
||||
* server = new V8DebugServer(runtime, port, waitForConnection);<br> |
||||
* System.out.println("V8 Debug Server listening on port "<br> |
||||
* + server.getPort());<br> |
||||
* server.start();<br> |
||||
* <br> |
||||
* //execute script and provide name for it<br>
|
||||
* runtime.executeVoidScript("var i = 15", "myscript.js", 0);<br> |
||||
* |
||||
* </code> |
||||
* |
||||
* @author piotr@genuitec.com |
||||
*/ |
||||
@SuppressWarnings("nls") |
||||
public class V8DebugServer { |
||||
|
||||
/** |
||||
* Name under which internal V8 debug object is going to be exposed in the runtime. |
||||
* You can change the name if you are passing a different one through {@code -expose-debug-as} |
||||
* flag. |
||||
*/ |
||||
public static String DEBUG_OBJECT_NAME = "__j2v8_Debug"; |
||||
|
||||
private static final String DEBUG_BREAK_HANDLER = "__j2v8_debug_handler"; |
||||
private static final String MAKE_BREAK_EVENT = "__j2v8_MakeBreakEvent"; |
||||
private static final String MAKE_COMPILE_EVENT = "__j2v8_MakeCompileEvent"; |
||||
private static final String SET_LISTENER = "setListener"; |
||||
private static final String V8_DEBUG_OBJECT = "Debug"; |
||||
|
||||
//Headers
|
||||
private static final String HEADER_TYPE = "Type: "; |
||||
private static final String HEADER_V8_VERSION = "V8-Version: "; |
||||
private static final String HEADER_PROTOCOL_VERSION = "Protocol-Version: "; |
||||
private static final String HEADER_EMBEDDING_HOST = "Embedding-Host: "; |
||||
|
||||
private static final String V8_VERSION = "4.10.253"; |
||||
private static final String J2V8_VERSION = "4.0.0"; |
||||
private static final String PROTOCOL_VERSION = "1"; |
||||
|
||||
//Protocol consts
|
||||
private static final Charset PROTOCOL_CHARSET = Charset.forName("UTF-8"); |
||||
private static final String PROTOCOL_EOL = "\r\n"; |
||||
private static final byte[] PROTOCOL_EOL_BYTES = PROTOCOL_EOL.getBytes(PROTOCOL_CHARSET); |
||||
private static final String PROTOCOL_CONTENT_LENGTH_HEADER = "Content-Length:"; |
||||
private static final byte[] PROTOCOL_CONTENT_LENGTH_BYTES = PROTOCOL_CONTENT_LENGTH_HEADER.getBytes(PROTOCOL_CHARSET); |
||||
private static final int PROTOCOL_BUFFER_SIZE = 4096; |
||||
|
||||
/** |
||||
* Utility method for simplification of configuring V8 for debugging support. |
||||
*/ |
||||
public static void configureV8ForDebugging() { |
||||
try { |
||||
V8.setFlags("-expose-debug-as=" + DEBUG_OBJECT_NAME); |
||||
} catch (Throwable t) { |
||||
t.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private ServerSocket server; |
||||
private Socket client; |
||||
private Object clientLock = new Object(); |
||||
|
||||
private V8 runtime; |
||||
private V8Object debugObject; |
||||
private V8Object runningStateDcp; |
||||
private V8Object stoppedStateDcp; |
||||
private boolean waitForConnection; |
||||
private boolean traceCommunication = false; |
||||
|
||||
private List<String> requests = new LinkedList<String>(); |
||||
|
||||
/** |
||||
* Creates V8DebugServer. |
||||
* |
||||
* @param runtime |
||||
* @param port |
||||
* @param waitForConnection |
||||
*/ |
||||
public V8DebugServer(final V8 runtime, final int port, final boolean waitForConnection) { |
||||
this.runtime = runtime; |
||||
this.waitForConnection = waitForConnection; |
||||
|
||||
V8Object debugScope = runtime.getObject(DEBUG_OBJECT_NAME); |
||||
if (debugScope == null) { |
||||
System.err.println("Cannot initialize debugger server - global debug object not found."); |
||||
return; |
||||
} |
||||
try { |
||||
debugObject = debugScope.getObject(V8_DEBUG_OBJECT); |
||||
} finally { |
||||
debugScope.close(); |
||||
} |
||||
|
||||
runtime.executeVoidScript("(function() {\n" |
||||
+ " " + DEBUG_OBJECT_NAME + ".Debug. " + MAKE_BREAK_EVENT + " = function (break_id,breakpoints_hit) {\n" |
||||
+ " return new " + DEBUG_OBJECT_NAME + ".BreakEvent(break_id,breakpoints_hit);\n" |
||||
+ " }\n" |
||||
+ " " + DEBUG_OBJECT_NAME + ".Debug. " + MAKE_COMPILE_EVENT + " = function(script,type) {\n" |
||||
+ " var scripts = " + DEBUG_OBJECT_NAME + ".Debug.scripts()\n" |
||||
+ " for (var i in scripts) {\n" |
||||
+ " if (scripts[i].id == script.id()) {\n" |
||||
+ " return new " + DEBUG_OBJECT_NAME + ".CompileEvent(scripts[i], type);\n" |
||||
+ " }\n" |
||||
+ " }\n" |
||||
+ " return {toJSONProtocol: function() {return ''}}\n" |
||||
+ " }\n" |
||||
+ "})()"); |
||||
try { |
||||
server = new ServerSocket(port); |
||||
} catch (Exception e) { |
||||
logError(e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns port on which server is listening or -1 if server failed to bound to a port. |
||||
* @return port or -1 if server failed to bound to a port |
||||
*/ |
||||
public int getPort() { |
||||
return (server != null) && server.isBound() ? server.getLocalPort() : -1; |
||||
} |
||||
|
||||
/** |
||||
* Output all communication to the console. For purpose of debugging V8DebugServer itself. |
||||
* @param value |
||||
*/ |
||||
public void setTraceCommunication(final boolean value) { |
||||
traceCommunication = value; |
||||
} |
||||
|
||||
/** |
||||
* Starts accepting client connections and blocks until a client connects |
||||
* if {@code waitForConnection} has been passed to V8DebugServer constructor. |
||||
*/ |
||||
public void start() { |
||||
if (server == null) { |
||||
return; |
||||
} |
||||
boolean waitForConnection = this.waitForConnection; |
||||
Thread clientThread = new Thread(new ClientLoop(), "J2V8 Debugger Server"); |
||||
clientThread.setDaemon(true); |
||||
clientThread.start(); |
||||
|
||||
setupEventHandler(); |
||||
|
||||
runningStateDcp = runtime.executeObjectScript("(function() {return new " + DEBUG_OBJECT_NAME + ".DebugCommandProcessor(null, true)})()"); |
||||
|
||||
if (waitForConnection) { |
||||
synchronized (clientLock) { |
||||
while (this.waitForConnection) { |
||||
try { |
||||
clientLock.wait(); |
||||
} catch (InterruptedException e) { |
||||
//ignore
|
||||
} |
||||
} |
||||
} |
||||
|
||||
//Process initial requests
|
||||
//Give 100ms for initial debugger connection setup
|
||||
try { |
||||
processRequests(100); |
||||
} catch (InterruptedException e) { |
||||
//ignore
|
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public void stop() { |
||||
try { |
||||
server.close(); |
||||
|
||||
synchronized (clientLock) { |
||||
if (client != null) { |
||||
client.close(); |
||||
client = null; |
||||
} |
||||
} |
||||
} catch (IOException e) { |
||||
logError(e); |
||||
} |
||||
|
||||
//release resources
|
||||
if (runningStateDcp != null) { |
||||
runningStateDcp.close(); |
||||
runningStateDcp = null; |
||||
} |
||||
if (debugObject != null) { |
||||
debugObject.close(); |
||||
debugObject = null; |
||||
} |
||||
if (stoppedStateDcp != null) { |
||||
stoppedStateDcp.close(); |
||||
stoppedStateDcp = null; |
||||
} |
||||
}; |
||||
|
||||
private void sendJson(String json) throws IOException { |
||||
json = json.replace("\\/", "/"); // Unescape slashes.
|
||||
sendMessage("", json); |
||||
} |
||||
|
||||
protected void logError(final Throwable t) { |
||||
t.printStackTrace(); |
||||
} |
||||
|
||||
private void sendMessage(final String header, final String contents) throws IOException { |
||||
synchronized (clientLock) { |
||||
if (!isConnected()) { |
||||
throw new IOException("There is no connected client."); |
||||
} |
||||
|
||||
byte[] contentBytes = contents.getBytes(PROTOCOL_CHARSET); |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
|
||||
//append custom headers
|
||||
sb.append(header); |
||||
|
||||
//append content length header
|
||||
sb.append(PROTOCOL_CONTENT_LENGTH_HEADER); |
||||
sb.append(Integer.toString(contentBytes.length)); |
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
//skip tools info
|
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
//send headers to the client
|
||||
client.getOutputStream().write(sb.toString().getBytes( |
||||
PROTOCOL_CHARSET)); |
||||
|
||||
//send contents to the client
|
||||
if (contentBytes.length > 0) { |
||||
client.getOutputStream().write(contentBytes); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean isConnected() { |
||||
synchronized (clientLock) { |
||||
return (server != null) && (client != null) && client.isConnected(); |
||||
} |
||||
} |
||||
|
||||
public void processRequests(final long timeout) throws InterruptedException { |
||||
if (server == null) { |
||||
return; |
||||
} |
||||
long start = System.currentTimeMillis(); |
||||
do { |
||||
String[] reqs; |
||||
do { |
||||
synchronized (requests) { |
||||
reqs = requests.toArray(new String[requests.size()]); |
||||
requests.clear(); |
||||
} |
||||
for (String req : reqs) { |
||||
try { |
||||
processRequest(req); |
||||
} catch (Exception e) { |
||||
logError(e); |
||||
} |
||||
} |
||||
} while (reqs.length > 0); |
||||
if (timeout > 0) { |
||||
Thread.sleep(10); |
||||
} |
||||
} while ((timeout > 0) && ((start + timeout) > System.currentTimeMillis())); |
||||
} |
||||
|
||||
private void processRequest(final String message) throws IOException { |
||||
if (traceCommunication) { |
||||
System.out.println("Got message: \n" + message.substring(0, Math.min(message.length(), 1000))); |
||||
} |
||||
V8Array params = new V8Array(runtime); |
||||
params.push(message); |
||||
|
||||
@SuppressWarnings("resource") |
||||
V8Object dcp = stoppedStateDcp != null ? stoppedStateDcp : runningStateDcp; |
||||
Object result = dcp.executeFunction("processDebugJSONRequest", params); |
||||
|
||||
String json = result.toString(); |
||||
|
||||
if ((stoppedStateDcp == null) && json.contains("\"running\":false")) { |
||||
//XXX Need to implement functionality by adding to V8 class
|
||||
// breakpoints before initial script or function execution
|
||||
json = json.replace("\"running\":false", "\"running\":true") |
||||
.replace("\"success\":true", "\"success\":false") |
||||
.replace("{\"", "{\"message\":\"Client requested suspension is not supported on J2V8.\",\""); |
||||
dcp.add("running_", true); |
||||
} |
||||
|
||||
if (traceCommunication) { |
||||
System.out.println("Returning response: \n" + json.substring(0, Math.min(json.length(), 1000))); |
||||
} |
||||
sendJson(json); |
||||
} |
||||
|
||||
private void setupEventHandler() { |
||||
EventHandler handler = new EventHandler(); |
||||
debugObject.registerJavaMethod(handler, DEBUG_BREAK_HANDLER); |
||||
V8Function debugHandler = null; |
||||
V8Array parameters = null; |
||||
try { |
||||
debugHandler = (V8Function) debugObject.getObject(DEBUG_BREAK_HANDLER); |
||||
parameters = new V8Array(runtime); |
||||
parameters.push(debugHandler); |
||||
debugObject.executeFunction(SET_LISTENER, parameters); |
||||
} finally { |
||||
if ((debugHandler != null) && !debugHandler.isReleased()) { |
||||
debugHandler.close(); |
||||
} |
||||
if ((parameters != null) && !parameters.isReleased()) { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void enterBreakLoop(final V8Object execState, final V8Object eventData) throws IOException { |
||||
try { |
||||
V8Array params = new V8Array(runtime); |
||||
try { |
||||
params.push(false); |
||||
stoppedStateDcp = execState.executeObjectFunction("debugCommandProcessor", params); |
||||
} finally { |
||||
params.close(); |
||||
} |
||||
|
||||
//send event to debugger
|
||||
int breakId = execState.getInteger("break_id"); |
||||
V8Array breakpointsHit = eventData.getArray("break_points_hit_"); |
||||
V8Object event = null; |
||||
|
||||
params = new V8Array(runtime); |
||||
try { |
||||
params.push(breakId); |
||||
params.push(breakpointsHit); |
||||
event = debugObject.executeObjectFunction(MAKE_BREAK_EVENT, params); |
||||
String json = event.executeStringFunction("toJSONProtocol", null); |
||||
if (traceCommunication) { |
||||
System.out.println("Sending event (Break):\n" + json); |
||||
} |
||||
sendJson(json); |
||||
} finally { |
||||
params.close(); |
||||
breakpointsHit.close(); |
||||
if (event != null) { |
||||
event.close(); |
||||
} |
||||
} |
||||
|
||||
//process requests until one of the resumes execution
|
||||
while (isConnected() && !stoppedStateDcp.executeBooleanFunction("isRunning", null)) { |
||||
try { |
||||
processRequests(10); |
||||
} catch (InterruptedException e) { |
||||
//ignore
|
||||
} |
||||
} |
||||
} finally { |
||||
stoppedStateDcp.close(); |
||||
stoppedStateDcp = null; |
||||
} |
||||
} |
||||
|
||||
private void sendCompileEvent(final V8Object eventData) throws IOException { |
||||
if (!isConnected()) { |
||||
return; |
||||
} |
||||
//send event to debugger
|
||||
int type = eventData.getInteger("type_"); |
||||
V8Object script = eventData.getObject("script_"); |
||||
V8Object event = null; |
||||
|
||||
V8Array params = new V8Array(runtime); |
||||
try { |
||||
params.push(script); |
||||
params.push(type); |
||||
event = debugObject.executeObjectFunction(MAKE_COMPILE_EVENT, params); |
||||
String json = event.executeStringFunction("toJSONProtocol", null); |
||||
if (traceCommunication) { |
||||
System.out.println("Sending event (CompileEvent):\n" + json.substring(0, Math.min(json.length(), 1000))); |
||||
} |
||||
if (json.length() > 0) { |
||||
sendJson(json); |
||||
} |
||||
} finally { |
||||
params.close(); |
||||
script.close(); |
||||
if (event != null) { |
||||
event.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private class EventHandler implements JavaVoidCallback { |
||||
|
||||
@Override |
||||
public void invoke(final V8Object receiver, final V8Array parameters) { |
||||
if ((parameters == null) || parameters.isUndefined()) { |
||||
return; |
||||
} |
||||
V8Object execState = null; |
||||
V8Object eventData = null; |
||||
try { |
||||
int event = parameters.getInteger(0); |
||||
execState = parameters.getObject(1); |
||||
eventData = parameters.getObject(2); |
||||
|
||||
if (traceCommunication) { |
||||
String type = "unknown"; |
||||
switch (event) { |
||||
case 1: |
||||
type = "Break"; |
||||
break; |
||||
case 2: |
||||
type = "Exception"; |
||||
break; |
||||
case 3: |
||||
type = "NewFunction"; |
||||
break; |
||||
case 4: |
||||
type = "BeforeCompile"; |
||||
break; |
||||
case 5: |
||||
type = "AfterCompile"; |
||||
break; |
||||
case 6: |
||||
type = "CompileError"; |
||||
break; |
||||
case 7: |
||||
type = "PromiseEvent"; |
||||
break; |
||||
case 8: |
||||
type = "AsyncTaskEvent"; |
||||
break; |
||||
} |
||||
System.out.println("V8 has emmitted an event of type " + type); |
||||
} |
||||
|
||||
if (!isConnected()) { |
||||
return; |
||||
} |
||||
|
||||
switch (event) { |
||||
case 1: //Break
|
||||
enterBreakLoop(execState, eventData); |
||||
break; |
||||
case 5: //afterCompile
|
||||
case 6: //compileError
|
||||
sendCompileEvent(eventData); |
||||
break; |
||||
case 2: //exception
|
||||
default: |
||||
} |
||||
} catch (Exception e) { |
||||
logError(e); |
||||
} finally { |
||||
safeRelease(execState); |
||||
safeRelease(eventData); |
||||
} |
||||
} |
||||
|
||||
private void safeRelease(final Releasable object) { |
||||
if ((object != null)) { |
||||
object.release(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private class ClientLoop implements Runnable { |
||||
|
||||
private int from; |
||||
|
||||
@Override |
||||
public void run() { |
||||
while (true) { |
||||
try { |
||||
Socket socket = server.accept(); |
||||
socket.setTcpNoDelay(true); |
||||
synchronized (clientLock) { |
||||
client = socket; |
||||
waitForConnection = false; |
||||
clientLock.notifyAll(); |
||||
} |
||||
startHandshake(); |
||||
processClientRequests(); |
||||
} catch (Exception e) { |
||||
synchronized (clientLock) { |
||||
if (client != null) { |
||||
try { |
||||
client.close(); |
||||
} catch (IOException ex) { |
||||
//ignore
|
||||
} |
||||
client = null; |
||||
} |
||||
} |
||||
logError(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void startHandshake() throws IOException { |
||||
StringBuilder sb = new StringBuilder(); |
||||
|
||||
sb.append(HEADER_V8_VERSION); |
||||
sb.append(V8_VERSION); |
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
sb.append(HEADER_PROTOCOL_VERSION); |
||||
sb.append(PROTOCOL_VERSION); |
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
sb.append(HEADER_EMBEDDING_HOST); |
||||
sb.append("j2v8 "); |
||||
sb.append(J2V8_VERSION); |
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
sb.append(HEADER_TYPE); |
||||
sb.append("connect"); |
||||
sb.append(PROTOCOL_EOL); |
||||
|
||||
sendMessage(sb.toString(), ""); |
||||
} |
||||
|
||||
private void processClientRequests() throws IOException { |
||||
final byte[] EMPTY_ARR = new byte[] {}; |
||||
|
||||
byte[] buf = new byte[PROTOCOL_BUFFER_SIZE]; |
||||
int bytesRead; |
||||
int offset = 0; |
||||
|
||||
//Message data
|
||||
boolean toolInfoSkipped = false; |
||||
byte[] messageBytes = EMPTY_ARR; |
||||
int contentLength = -1; |
||||
|
||||
InputStream cIn; |
||||
synchronized (clientLock) { |
||||
cIn = client.getInputStream(); |
||||
} |
||||
|
||||
while ((bytesRead = cIn.read(buf, offset, PROTOCOL_BUFFER_SIZE - offset)) > 0) { |
||||
bytesRead += offset; |
||||
from = 0; |
||||
do { |
||||
if (contentLength < 0) { |
||||
contentLength = readContentLength(buf, bytesRead); |
||||
if (contentLength < 0) { |
||||
break; |
||||
} |
||||
} |
||||
if (!toolInfoSkipped) { |
||||
toolInfoSkipped = skipToolInfo(buf, bytesRead); |
||||
if (!toolInfoSkipped) { |
||||
break; |
||||
} |
||||
} |
||||
int length = Math.min(contentLength - messageBytes.length, bytesRead - from); |
||||
messageBytes = join(messageBytes, buf, from, length); |
||||
from += length; |
||||
if (messageBytes.length == contentLength) { |
||||
String message = new String(messageBytes, PROTOCOL_CHARSET); |
||||
synchronized (requests) { |
||||
requests.add(message); |
||||
} |
||||
contentLength = -1; |
||||
toolInfoSkipped = false; |
||||
messageBytes = EMPTY_ARR; |
||||
} |
||||
} while (from < bytesRead); |
||||
if (from < bytesRead) { |
||||
System.arraycopy(buf, from, buf, 0, bytesRead - from); |
||||
offset = bytesRead - from; |
||||
} else { |
||||
offset = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private int readContentLength(final byte[] bytes, final int to) throws IOException { |
||||
int pos = indexOf(PROTOCOL_CONTENT_LENGTH_BYTES, bytes, from, to); |
||||
if (pos < 0) { |
||||
return -1; |
||||
} |
||||
pos += PROTOCOL_CONTENT_LENGTH_BYTES.length; |
||||
int end = indexOf(PROTOCOL_EOL_BYTES, bytes, pos, to); |
||||
if (end < 0) { |
||||
return -1; |
||||
} |
||||
String str = new String(bytes, pos, end - pos, PROTOCOL_CHARSET); |
||||
int contentLength; |
||||
try { |
||||
contentLength = Integer.parseInt(str.trim()); |
||||
} catch (Exception ex) { |
||||
throw new IOException("Invalid content length header: '" + str + "' in message" + |
||||
new String(bytes, PROTOCOL_CHARSET)); |
||||
} |
||||
from = end + PROTOCOL_EOL_BYTES.length; |
||||
return contentLength; |
||||
} |
||||
|
||||
private boolean skipToolInfo(final byte[] bytes, final int n) { |
||||
int end = indexOf(PROTOCOL_EOL_BYTES, bytes, from, n); |
||||
if (end < 0) { |
||||
return false; |
||||
} |
||||
from = end + PROTOCOL_EOL_BYTES.length; |
||||
return true; |
||||
} |
||||
|
||||
private int indexOf(final byte[] pattern, final byte[] array, final int start, final int end) { |
||||
int len = pattern.length; |
||||
for (int i = start; i < end; i++) { |
||||
for (int j = 0; j <= len; j++) { |
||||
if (j == len) { |
||||
//pattern matches at i
|
||||
return i; |
||||
} |
||||
if (((i + j) >= end) || (array[i + j] != pattern[j])) { |
||||
//pattern does not match at i
|
||||
break; |
||||
} |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
private byte[] join(final byte[] arr1, final byte[] arr2, final int startPos, final int length) { |
||||
byte[] res = new byte[arr1.length + length]; |
||||
System.arraycopy(arr1, 0, res, 0, arr1.length); |
||||
System.arraycopy(arr2, startPos, res, arr1.length, length); |
||||
return res; |
||||
} |
||||
|
||||
}; |
||||
} |
@ -1,40 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents 'Array' mirrors. |
||||
*/ |
||||
public class ArrayMirror extends ObjectMirror { |
||||
|
||||
private static final String LENGTH = "length"; |
||||
|
||||
ArrayMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isArray() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns the length of the array pointed to by this Array Mirror |
||||
* |
||||
* @return The length of the array. |
||||
*/ |
||||
public int length() { |
||||
return v8Object.executeIntegerFunction(LENGTH, null); |
||||
} |
||||
|
||||
} |
@ -1,33 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents JavaScript 'Boolean' Mirrors |
||||
*/ |
||||
public class BooleanMirror extends ValueMirror { |
||||
|
||||
BooleanMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isBoolean() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return v8Object.executeStringFunction("toText", null); |
||||
} |
||||
} |
@ -1,225 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents a single stack frame accessible from the |
||||
* current execution state. |
||||
*/ |
||||
public class Frame extends Mirror { |
||||
|
||||
private static final String SOURCE_TEXT = "sourceText"; |
||||
private static final String FUNC = "func"; |
||||
private static final String COLUMN = "column"; |
||||
private static final String LINE = "line"; |
||||
private static final String POSITION = "position"; |
||||
private static final String NAME = "name"; |
||||
private static final String SCRIPT = "script"; |
||||
private static final String SCOPE = "scope"; |
||||
private static final String ARGUMENT_VALUE = "argumentValue"; |
||||
private static final String ARGUMENT_NAME = "argumentName"; |
||||
private static final String LOCAL_COUNT = "localCount"; |
||||
private static final String ARGUMENT_COUNT = "argumentCount"; |
||||
private static final String SCOPE_COUNT = "scopeCount"; |
||||
private static final String LOCAL_NAME = "localName"; |
||||
private static final String LOCAL_VALUE = "localValue"; |
||||
private static final String SOURCE_LOCATION = "sourceLocation"; |
||||
|
||||
public Frame(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of accessible scopes from this stack frame. |
||||
* |
||||
* @return The number of accessible scopes |
||||
*/ |
||||
public int getScopeCount() { |
||||
return v8Object.executeIntegerFunction(SCOPE_COUNT, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the SourceLocation of this Frame. |
||||
* |
||||
* @return The SourceLocation of this Frame. |
||||
*/ |
||||
public SourceLocation getSourceLocation() { |
||||
V8Object sourceLocation = v8Object.executeObjectFunction(SOURCE_LOCATION, null); |
||||
FunctionMirror function = getFunction(); |
||||
String functionScriptName = function.getScriptName(); |
||||
try { |
||||
String scriptName = null; |
||||
V8Object scriptObject = (V8Object) sourceLocation.get(SCRIPT); |
||||
if (scriptObject != null) { |
||||
scriptName = scriptObject.getString(NAME); |
||||
scriptObject.close(); |
||||
} |
||||
if ((scriptName == null) && (functionScriptName != null)) { |
||||
scriptName = functionScriptName; |
||||
} else { |
||||
scriptName = "undefined"; |
||||
} |
||||
return new SourceLocation(scriptName, |
||||
sourceLocation.getInteger(POSITION), |
||||
sourceLocation.getInteger(LINE), |
||||
sourceLocation.getInteger(COLUMN), |
||||
sourceLocation.getString(SOURCE_TEXT)); |
||||
} finally { |
||||
function.close(); |
||||
sourceLocation.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of arguments to this frame. |
||||
* |
||||
* @return The number of arguments passed to this frame. |
||||
*/ |
||||
public int getArgumentCount() { |
||||
return v8Object.executeIntegerFunction(ARGUMENT_COUNT, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the argument at the given index. |
||||
* |
||||
* @param index The index of the argument name to return. |
||||
* @return The name of argument at the given index. |
||||
*/ |
||||
public String getArgumentName(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
try { |
||||
return v8Object.executeStringFunction(ARGUMENT_NAME, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of the argument at the given index. |
||||
* |
||||
* @param index The index of the argument value to return. |
||||
* @return The value of argument at the given index. |
||||
*/ |
||||
public ValueMirror getArgumentValue(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
V8Object result = null; |
||||
try { |
||||
result = v8Object.executeObjectFunction(ARGUMENT_VALUE, parameters); |
||||
if (!isValue(result)) { |
||||
throw new IllegalStateException("Argument value is not a ValueMirror"); |
||||
} |
||||
return new ValueMirror(result); |
||||
} finally { |
||||
parameters.close(); |
||||
if (result != null) { |
||||
result.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of the local variable at the given index. |
||||
* |
||||
* @param index The index of the local to return. |
||||
* @return The value of local at the given index. |
||||
*/ |
||||
public ValueMirror getLocalValue(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
V8Object result = null; |
||||
try { |
||||
result = v8Object.executeObjectFunction(LOCAL_VALUE, parameters); |
||||
if (!isValue(result)) { |
||||
throw new IllegalStateException("Local value is not a ValueMirror"); |
||||
} |
||||
return createMirror(result); |
||||
} finally { |
||||
parameters.close(); |
||||
if (result != null) { |
||||
result.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of local variables in this frame. |
||||
* |
||||
* @return The number of local variables accessible from this stack frame. |
||||
*/ |
||||
public int getLocalCount() { |
||||
return v8Object.executeIntegerFunction(LOCAL_COUNT, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the local variable at the given index. |
||||
* |
||||
* @param index The index of the local variable name to return. |
||||
* @return The name of local variable at the given index. |
||||
*/ |
||||
public String getLocalName(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
try { |
||||
return v8Object.executeStringFunction(LOCAL_NAME, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the scope at a given index. |
||||
* |
||||
* @param index The index |
||||
* @return The scope |
||||
*/ |
||||
public Scope getScope(final int index) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(index); |
||||
V8Object scope = null; |
||||
try { |
||||
scope = v8Object.executeObjectFunction(SCOPE, parameters); |
||||
return new Scope(scope); |
||||
} finally { |
||||
parameters.close(); |
||||
if (scope != null) { |
||||
scope.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the Function associated with this particular debug frame. |
||||
* |
||||
* @return The Function for this debug frame. |
||||
*/ |
||||
public FunctionMirror getFunction() { |
||||
V8Object function = null; |
||||
try { |
||||
function = v8Object.executeObjectFunction(FUNC, null); |
||||
return new FunctionMirror(function); |
||||
} finally { |
||||
if (function != null) { |
||||
function.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean isFrame() { |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,56 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents JavaScript 'Function' Mirrors |
||||
*/ |
||||
public class FunctionMirror extends ObjectMirror { |
||||
|
||||
private static final String NAME = "name"; |
||||
private static final String SCRIPT = "script"; |
||||
|
||||
FunctionMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of this Function. |
||||
* |
||||
* @return The name of this function |
||||
*/ |
||||
public String getName() { |
||||
return v8Object.executeStringFunction(NAME, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the Script associated with |
||||
* this FunctionMirror. |
||||
* |
||||
* @return The name of the script. |
||||
*/ |
||||
public String getScriptName() { |
||||
V8Object script = v8Object.executeObjectFunction(SCRIPT, null); |
||||
try { |
||||
return script.executeStringFunction(NAME, null); |
||||
} finally { |
||||
script.close(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean isFunction() { |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,294 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.V8ResultUndefined; |
||||
|
||||
/** |
||||
* A mirror is used to represent a copy (mirror) of a runtime object |
||||
* during a debug session. |
||||
* |
||||
* Mirror hierarchy: |
||||
* - Mirror |
||||
* - ValueMirror |
||||
* - UndefinedMirror |
||||
* - NullMirror |
||||
* - NumberMirror |
||||
* - StringMirror |
||||
* - ObjectMirror |
||||
* - FunctionMirror |
||||
* - UnresolvedFunctionMirror |
||||
* - ArrayMirror |
||||
* - DateMirror |
||||
* - RegExpMirror |
||||
* - ErrorMirror |
||||
* - PromiseMirror |
||||
* - PropertyMirror |
||||
* - InternalPropertyMirror |
||||
* - FrameMirror |
||||
* - ScriptMirror |
||||
*/ |
||||
public class Mirror implements Releasable { |
||||
|
||||
private static final String IS_UNDEFINED = "isUndefined"; |
||||
private static final String IS_NULL = "isNull"; |
||||
private static final String IS_STRING = "isString"; |
||||
private static final String IS_ARRAY = "isArray"; |
||||
private static final String IS_FUNCTION = "isFunction"; |
||||
private static final String IS_BOOLEAN = "isBoolean"; |
||||
private static final String IS_NUMBER = "isNumber"; |
||||
private static final String IS_OBJECT = "isObject"; |
||||
private static final String IS_VALUE = "isValue"; |
||||
|
||||
protected V8Object v8Object; |
||||
|
||||
Mirror(final V8Object v8Object) { |
||||
this.v8Object = v8Object.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to the type 'undefined'. |
||||
* False otherwise. |
||||
* |
||||
* @return True iff this mirror object points to an 'undefined' type. |
||||
*/ |
||||
public boolean isUndefined() { |
||||
return v8Object.executeBooleanFunction(IS_UNDEFINED, null); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'value' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'value' type. |
||||
*/ |
||||
public boolean isValue() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to 'null'. |
||||
* |
||||
* @return True iff this mirror object points to a 'null'. |
||||
*/ |
||||
public boolean isNull() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'boolean' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'boolean' type. |
||||
*/ |
||||
public boolean isBoolean() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'number' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'number' type. |
||||
*/ |
||||
public boolean isNumber() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'String' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'String' type. |
||||
*/ |
||||
public boolean isString() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to an 'Object' type. |
||||
* |
||||
* @return True iff this mirror object points to an 'Object' type. |
||||
*/ |
||||
public boolean isObject() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'Function' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'Function' type. |
||||
*/ |
||||
public boolean isFunction() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to an 'Array' type. |
||||
* |
||||
* @return True iff this mirror object points to an 'Array' type. |
||||
*/ |
||||
public boolean isArray() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'Function' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'Function' type. |
||||
*/ |
||||
public boolean isFrame() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if this mirror object points to a 'Property' type. |
||||
* |
||||
* @return True iff this mirror object points to a 'Property' type. |
||||
*/ |
||||
public boolean isProperty() { |
||||
return false; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.io.Closeable#close() |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
if ((v8Object != null) && !v8Object.isReleased()) { |
||||
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); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isObject(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_OBJECT, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isNumber(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_NUMBER, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isBoolean(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_BOOLEAN, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isFunction(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_FUNCTION, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isArray(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_ARRAY, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isString(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_STRING, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isUndefined(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_UNDEFINED, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static boolean isNull(final V8Object mirror) { |
||||
try { |
||||
return mirror.executeBooleanFunction(IS_NULL, null); |
||||
} catch (V8ResultUndefined e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
protected static ValueMirror createMirror(final V8Object mirror) { |
||||
if (isNull(mirror)) { |
||||
return new NullMirror(mirror); |
||||
} else if (isUndefined(mirror)) { |
||||
return new UndefinedMirror(mirror); |
||||
} else if (isFunction(mirror)) { |
||||
return new FunctionMirror(mirror); |
||||
} else if (isArray(mirror)) { |
||||
return new ArrayMirror(mirror); |
||||
} else if (isObject(mirror)) { |
||||
return new ObjectMirror(mirror); |
||||
} else if (isString(mirror)) { |
||||
return new StringMirror(mirror); |
||||
} else if (isNumber(mirror)) { |
||||
return new NumberMirror(mirror); |
||||
} else if (isBoolean(mirror)) { |
||||
return new BooleanMirror(mirror); |
||||
} |
||||
return new ValueMirror(mirror); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return v8Object.toString(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object obj) { |
||||
if (obj == null) { |
||||
return false; |
||||
} |
||||
if (!(obj instanceof Mirror)) { |
||||
return false; |
||||
} |
||||
return v8Object.equals(((Mirror) obj).v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return v8Object.hashCode(); |
||||
} |
||||
} |
@ -1,35 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents 'Null' Mirrors |
||||
*/ |
||||
public class NullMirror extends ValueMirror { |
||||
|
||||
|
||||
NullMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isNull() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "null"; |
||||
} |
||||
|
||||
} |
@ -1,34 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents JavaScript 'Number' Mirrors |
||||
*/ |
||||
public class NumberMirror extends ValueMirror { |
||||
|
||||
NumberMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isNumber() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return v8Object.executeStringFunction("toText", null); |
||||
} |
||||
|
||||
} |
@ -1,98 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents 'Object' mirrors. |
||||
*/ |
||||
public class ObjectMirror extends ValueMirror { |
||||
|
||||
private static final String PROPERTIES = "properties"; |
||||
private static final String PROPERTY_NAMES = "propertyNames"; |
||||
|
||||
public enum PropertyKind { |
||||
Named(1), Indexed(2); |
||||
int index; |
||||
|
||||
private PropertyKind(final int index) { |
||||
this.index = index; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return v8Object.toString(); |
||||
} |
||||
|
||||
ObjectMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isObject() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns all the property names for the given object. |
||||
* |
||||
* @param kind Indicate whether named, indexed or both kinds of properties are requested. |
||||
* @param limit Limit the number of properties returned to the specified value |
||||
* @return All the property names for a given object |
||||
*/ |
||||
public String[] getPropertyNames(final PropertyKind kind, final int limit) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(kind.index); |
||||
parameters.push(limit); |
||||
V8Array propertyNames = null; |
||||
try { |
||||
propertyNames = v8Object.executeArrayFunction(PROPERTY_NAMES, parameters); |
||||
String[] result = new String[propertyNames.length()]; |
||||
for (int i = 0; i < result.length; i++) { |
||||
result[i] = propertyNames.getString(i); |
||||
} |
||||
return result; |
||||
} finally { |
||||
parameters.close(); |
||||
if (propertyNames != null) { |
||||
propertyNames.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return the properties for this object as an array of PropertyMirror objects. |
||||
* |
||||
* @param kind Indicate whether named, indexed or both kinds of properties are requested |
||||
* @param limit Limit the number of properties returned to the specified value |
||||
* @return {Array} Property mirrors for this object |
||||
*/ |
||||
public PropertiesArray getProperties(final PropertyKind kind, final int limit) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(kind.index); |
||||
parameters.push(limit); |
||||
V8Array result = null; |
||||
try { |
||||
result = v8Object.executeArrayFunction(PROPERTIES, parameters); |
||||
return new PropertiesArray(result); |
||||
} finally { |
||||
parameters.close(); |
||||
if ((result != null) && !result.isReleased()) { |
||||
result.close(); |
||||
result = null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,73 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Provides typed access to a set of properties. |
||||
*/ |
||||
public class PropertiesArray implements Releasable { |
||||
|
||||
private V8Array v8Array; |
||||
|
||||
PropertiesArray(final V8Array v8Object) { |
||||
v8Array = v8Object.twin(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the PropertyMiror at a given index. |
||||
* |
||||
* @param index The index of the property |
||||
* @return The property at the given index |
||||
*/ |
||||
public PropertyMirror getProperty(final int index) { |
||||
V8Object result = v8Array.getObject(index); |
||||
try { |
||||
return new PropertyMirror(result); |
||||
} finally { |
||||
result.close(); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.io.Closeable#close() |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
if (!v8Array.isReleased()) { |
||||
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. |
||||
* |
||||
* @return The length of this array. |
||||
*/ |
||||
public int length() { |
||||
return v8Array.length(); |
||||
} |
||||
|
||||
} |
@ -1,52 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents JavaScript 'Property' Mirrors |
||||
*/ |
||||
public class PropertyMirror extends Mirror { |
||||
|
||||
PropertyMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of this property. |
||||
* |
||||
* @return The name of this property. |
||||
*/ |
||||
public String getName() { |
||||
return v8Object.executeStringFunction("name", null); |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of this property. |
||||
* |
||||
* @return The value of this property. |
||||
*/ |
||||
public Mirror getValue() { |
||||
V8Object mirror = v8Object.executeObjectFunction("value", null); |
||||
try { |
||||
return createMirror(mirror); |
||||
} finally { |
||||
mirror.close(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean isProperty() { |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,156 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.V8Value; |
||||
|
||||
/** |
||||
* Represents a JavaScope scope accessible from the current stack frame |
||||
* during debug break. |
||||
* |
||||
*/ |
||||
public class Scope extends Mirror { |
||||
|
||||
private static final String SCOPE_OBJECT = "scopeObject"; |
||||
private static final String SCOPE_TYPE = "scopeType"; |
||||
private static final String SET_VARIABLE_VALUE = "setVariableValue"; |
||||
|
||||
/** |
||||
* Represents the different types of scopes available. |
||||
*/ |
||||
public static enum ScopeType { |
||||
Global(0), Local(1), With(2), Closure(3), Catch(4), Block(5), Script(6); |
||||
int index; |
||||
|
||||
private ScopeType(final int index) { |
||||
this.index = index; |
||||
} |
||||
} |
||||
|
||||
Scope(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
/** |
||||
* Returns the type of this scope. |
||||
* |
||||
* @return The type of scope. |
||||
*/ |
||||
public ScopeType getType() { |
||||
return ScopeType.values()[v8Object.executeIntegerFunction(SCOPE_TYPE, null)]; |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of a variable in this scope. |
||||
* |
||||
* @param name The name of the variable |
||||
* @param value The value |
||||
*/ |
||||
public void setVariableValue(final String name, final int value) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(name); |
||||
parameters.push(value); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of a variable in this scope. |
||||
* |
||||
* @param name The name of the variable |
||||
* @param value The value |
||||
*/ |
||||
public void setVariableValue(final String name, final V8Value value) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(name); |
||||
parameters.push(value); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of a variable in this scope. |
||||
* |
||||
* @param name The name of the variable |
||||
* @param value The value |
||||
*/ |
||||
public void setVariableValue(final String name, final boolean value) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(name); |
||||
parameters.push(value); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of a variable in this scope. |
||||
* |
||||
* @param name The name of the variable |
||||
* @param value The value |
||||
*/ |
||||
public void setVariableValue(final String name, final String value) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(name); |
||||
parameters.push(value); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of a variable in this scope. |
||||
* |
||||
* @param name The name of the variable |
||||
* @param value The value |
||||
*/ |
||||
public void setVariableValue(final String name, final double value) { |
||||
V8Array parameters = new V8Array(v8Object.getRuntime()); |
||||
parameters.push(name); |
||||
parameters.push(value); |
||||
try { |
||||
v8Object.executeVoidFunction(SET_VARIABLE_VALUE, parameters); |
||||
} finally { |
||||
parameters.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the underlying V8Object that represents this scope. |
||||
* |
||||
* @return The underlying V8Object that represents this scope. |
||||
*/ |
||||
public ObjectMirror getScopeObject() { |
||||
V8Object mirror = null; |
||||
try { |
||||
mirror = v8Object.executeObjectFunction(SCOPE_OBJECT, null); |
||||
return (ObjectMirror) createMirror(mirror); |
||||
} finally { |
||||
if ( mirror != null ) { |
||||
mirror.close(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -1,84 +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.debug.mirror; |
||||
|
||||
/** |
||||
* Represents a JS Script location. |
||||
*/ |
||||
public class SourceLocation { |
||||
|
||||
private final String scriptName; |
||||
private final int position; |
||||
private final int line; |
||||
private final int column; |
||||
private String sourceText; |
||||
|
||||
/** |
||||
* Represents a JS Script Source Location |
||||
* @param scriptName The name of the script |
||||
* @param position The position in the script |
||||
* @param line The line number |
||||
* @param column The column number |
||||
* @param sourceText The sourceCode at this location |
||||
*/ |
||||
public SourceLocation(final String scriptName, final int position, final int line, final int column, final String sourceText) { |
||||
this.scriptName = scriptName; |
||||
this.position = position; |
||||
this.line = line; |
||||
this.column = column; |
||||
this.sourceText = sourceText; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return scriptName + " : " + position + " : " + line + " : " + column + " : " + sourceText; |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the script for this SourceLocation. |
||||
* @return The name of the script |
||||
*/ |
||||
public String getScriptName() { |
||||
return scriptName; |
||||
} |
||||
|
||||
/** |
||||
* Returns the position of this SourceLocation. |
||||
* @return The position of this SourceLocation. |
||||
*/ |
||||
public int getPosition() { |
||||
return position; |
||||
} |
||||
|
||||
/** |
||||
* Returns the line number of this SourceLocation. |
||||
* @return The line number of this SourceLocation. |
||||
*/ |
||||
public int getLine() { |
||||
return line; |
||||
} |
||||
|
||||
/** |
||||
* Returns the column number of this SourceLocation. |
||||
* @return The column number of this SourceLocation. |
||||
*/ |
||||
public int getColumn() { |
||||
return column; |
||||
} |
||||
|
||||
/** |
||||
* Returns the source text for this SourceLocation. |
||||
* @return The source text for this SourceLocation. |
||||
*/ |
||||
public String getSourceText() { |
||||
return sourceText; |
||||
} |
||||
} |
@ -1,34 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents JavaScript 'String' Mirrors |
||||
*/ |
||||
public class StringMirror extends ValueMirror { |
||||
|
||||
StringMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isString() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return v8Object.executeStringFunction("toText", null); |
||||
} |
||||
|
||||
} |
@ -1,35 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents 'Undefined' Mirrors |
||||
*/ |
||||
public class UndefinedMirror extends ValueMirror { |
||||
|
||||
|
||||
UndefinedMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isUndefined() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "undefined"; |
||||
} |
||||
|
||||
} |
@ -1,40 +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.debug.mirror; |
||||
|
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Represents 'Value' Mirrors (Objects, Numbers, Strings, ...). |
||||
*/ |
||||
public class ValueMirror extends Mirror { |
||||
|
||||
private static final String VALUE = "value"; |
||||
|
||||
ValueMirror(final V8Object v8Object) { |
||||
super(v8Object); |
||||
} |
||||
|
||||
/** |
||||
* Returns the Object that this mirror represents. |
||||
* |
||||
* @return The object that this mirror represents. |
||||
*/ |
||||
public Object getValue() { |
||||
return v8Object.executeFunction(VALUE, null); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isValue() { |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,7 +0,0 @@
|
||||
package com.eclipsesource.v8.inspector; |
||||
|
||||
public interface DebuggerConnectionListener { |
||||
public void onDebuggerConnected(); |
||||
|
||||
public void onDebuggerDisconnected(); |
||||
} |
@ -1,67 +0,0 @@
|
||||
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<DebuggerConnectionListener> debuggerConnectionListeners; |
||||
|
||||
protected V8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate, final String contextName) { |
||||
this.runtime = runtime; |
||||
inspectorPtr = runtime.createInspector(inspectorDelegate, contextName); |
||||
debuggerConnectionListeners = new ArrayList<DebuggerConnectionListener>(); |
||||
} |
||||
|
||||
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(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,7 +0,0 @@
|
||||
package com.eclipsesource.v8.inspector; |
||||
|
||||
public interface V8InspectorDelegate { |
||||
public void onResponse(String message); |
||||
|
||||
public void waitFrontendMessageOnPause(); |
||||
} |
@ -1,69 +0,0 @@
|
||||
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(); |
||||
} |
||||
|
||||
} |
@ -1,94 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2016 Brandon Sanders |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* Brandon Sanders - initial API and implementation and/or initial documentation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import com.eclipsesource.v8.V8; |
||||
|
||||
/** |
||||
* Wrapper class for an {@link com.eclipsesource.v8.V8} instance that allows |
||||
* a V8 instance to be invoked from across threads without explicitly acquiring |
||||
* or releasing locks. |
||||
* |
||||
* This class does not guarantee the safety of any objects stored in or accessed |
||||
* from the wrapped V8 instance; it only enables callers to interact with a V8 |
||||
* instance from any thread. The V8 instance represented by this class should |
||||
* still be treated with thread safety in mind |
||||
* |
||||
* @author Brandon Sanders [brandon@alicorn.io] |
||||
* @author R. Ian Bull - Additional API |
||||
*/ |
||||
public final class ConcurrentV8 { |
||||
private V8 v8 = null; |
||||
|
||||
/** |
||||
* Create a new ConcurrentV8. A ConcurrentV8 allows multiple |
||||
* threads to work with the same V8 engine by releasing |
||||
* the locks between calls. |
||||
*/ |
||||
public ConcurrentV8() { |
||||
v8 = V8.createV8Runtime(); |
||||
v8.getLocker().release(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the V8 runtime backing by this ConcurrentV8 |
||||
* |
||||
* @return The V8 runtime backing this ConcurrentV8 |
||||
*/ |
||||
public V8 getV8() { |
||||
return v8; |
||||
} |
||||
|
||||
/** |
||||
* Runs an {@link V8Runnable} on the V8 thread. |
||||
* |
||||
* <b>Note: </b> This method executes synchronously, not asynchronously; |
||||
* it will not return until the passed {@link V8Runnable} is done |
||||
* executing. The method is also synchronized, so it will block until it |
||||
* gets a chance to run. |
||||
* |
||||
* @param runnable {@link V8Runnable} to run. |
||||
*/ |
||||
public synchronized void run(final V8Runnable runnable) { |
||||
try { |
||||
v8.getLocker().acquire(); |
||||
runnable.run(v8); |
||||
} finally { |
||||
if ((v8 != null) && (v8.getLocker() != null) && v8.getLocker().hasLock()) { |
||||
v8.getLocker().release(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Releases the underlying {@link V8} instance. |
||||
* |
||||
* This method should be invoked once you're done using this object, |
||||
* otherwise a large amount of garbage could be left on the JVM due to |
||||
* native resources. |
||||
* |
||||
* <b>Note:</b> If this method has already been called once, it |
||||
* will do nothing. |
||||
*/ |
||||
public void release() { |
||||
if ((v8 != null) && !v8.isReleased()) { |
||||
// Release the V8 instance from the V8 thread context.
|
||||
run(new V8Runnable() { |
||||
@Override |
||||
public void run(final V8 v8) { |
||||
if ((v8 != null) && !v8.isReleased()) { |
||||
v8.close(); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
@ -1,138 +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; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
|
||||
import com.eclipsesource.v8.ReferenceHandler; |
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Value; |
||||
|
||||
/** |
||||
* A memory manager that tracks all V8 Handles while the object is registered. |
||||
* Once released, all V8 handles that were created while the memory manager |
||||
* was active, will be released. |
||||
* |
||||
* It is important that no V8 handles (V8Objects, V8Arrays, etc...) that are |
||||
* created while the memory manager is active, are persisted. |
||||
* |
||||
*/ |
||||
public class MemoryManager { |
||||
|
||||
private MemoryManagerReferenceHandler memoryManagerReferenceHandler; |
||||
private V8 v8; |
||||
private ArrayList<V8Value> references = new ArrayList<V8Value>(); |
||||
private boolean releasing = false; |
||||
private boolean released = false; |
||||
|
||||
/** |
||||
* Creates and registered a Memory Manager. After this, all V8 handles will be |
||||
* tracked until release is called. |
||||
* |
||||
* @param v8 The V8 runtime to register this Memory Manager on |
||||
*/ |
||||
public MemoryManager(final V8 v8) { |
||||
this.v8 = v8; |
||||
memoryManagerReferenceHandler = new MemoryManagerReferenceHandler(); |
||||
v8.addReferenceHandler(memoryManagerReferenceHandler); |
||||
} |
||||
|
||||
/** |
||||
* Returns the number of handles currently being tracked by this |
||||
* memory manager. |
||||
* |
||||
* Throws an IllegalStateException if the memory manager is used after it's |
||||
* been released. |
||||
* |
||||
* @return The object reference count |
||||
*/ |
||||
public int getObjectReferenceCount() { |
||||
checkReleased(); |
||||
return references.size(); |
||||
} |
||||
|
||||
/** |
||||
* Persist an object that is currently being managed by this Manager. |
||||
* |
||||
* Objects that are being managed by a MemoryManager will be released |
||||
* once the MemoryManager is released. If an object is persisted, it will |
||||
* be remove from the MemoryManager's control and therefore will not |
||||
* be released. |
||||
* |
||||
* @param object The object to persist |
||||
*/ |
||||
public void persist(final V8Value object) { |
||||
v8.getLocker().checkThread(); |
||||
checkReleased(); |
||||
references.remove(object); |
||||
} |
||||
|
||||
/** |
||||
* Checks if the memory manager has been released or not. Released memory |
||||
* managers can no longer be used. |
||||
* |
||||
* @return True if this memory manager has been released, false otherwise. |
||||
*/ |
||||
public boolean isReleased() { |
||||
return released; |
||||
} |
||||
|
||||
/** |
||||
* Releases this Memory Manager and all V8Objects that were created while |
||||
* this memory manager was active. |
||||
*/ |
||||
public void release() { |
||||
v8.getLocker().checkThread(); |
||||
if (released) { |
||||
return; |
||||
} |
||||
releasing = true; |
||||
try { |
||||
for (V8Value reference : references) { |
||||
reference.close(); |
||||
} |
||||
v8.removeReferenceHandler(memoryManagerReferenceHandler); |
||||
references.clear(); |
||||
} finally { |
||||
releasing = false; |
||||
} |
||||
released = true; |
||||
} |
||||
|
||||
private void checkReleased() { |
||||
if (released) { |
||||
throw new IllegalStateException("Memory manager released"); |
||||
} |
||||
} |
||||
|
||||
private class MemoryManagerReferenceHandler implements ReferenceHandler { |
||||
|
||||
@Override |
||||
public void v8HandleCreated(final V8Value object) { |
||||
references.add(object); |
||||
} |
||||
|
||||
@Override |
||||
public void v8HandleDisposed(final V8Value object) { |
||||
if (!releasing) { |
||||
Iterator<V8Value> iterator = references.iterator(); |
||||
while (iterator.hasNext()) { |
||||
if (iterator.next() == object) { |
||||
iterator.remove(); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,55 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2017 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
/** |
||||
* Adapt all instances of a single type from JavaScript to Java. |
||||
* The TypeAdapter can be used with the V8ObjectUtils to allow users to customize |
||||
* the conversion. |
||||
*/ |
||||
public abstract class SingleTypeAdapter implements TypeAdapter { |
||||
|
||||
private int typeToAdapt; |
||||
|
||||
/** |
||||
* Create a SingleTypeAdapter |
||||
* |
||||
* @param typeToAdapt The V8 Type this TypeAdapter should be applied to. |
||||
*/ |
||||
public SingleTypeAdapter(final int typeToAdapt) { |
||||
this.typeToAdapt = typeToAdapt; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see com.eclipsesource.v8.utils.TypeAdapter#adapt(int, java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public Object adapt(final int type, final Object value) { |
||||
if (type == typeToAdapt) { |
||||
return adapt(value); |
||||
} |
||||
return TypeAdapter.DEFAULT; |
||||
} |
||||
|
||||
/** |
||||
* Adapt an object from V8 to Java. |
||||
* |
||||
* If the value is a V8Value (V8Object) then it will be released after |
||||
* this method is called. If you wish to retain the object, call |
||||
* ((V8Value)value).twin(); |
||||
* |
||||
* @param value The V8 Object to be converted. |
||||
* @return The adapted Java Object or {@link TypeAdapter#DEFAULT} for the default conversion. |
||||
*/ |
||||
public abstract Object adapt(final Object value); |
||||
|
||||
} |
@ -1,39 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2017 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
/** |
||||
* An interface which allows a plug-able conversion from V8Value types to Java objects. |
||||
* The TypeAdapter can be used with the V8ObjectUtils to allow users to customize |
||||
* the conversion. |
||||
*/ |
||||
public interface TypeAdapter { |
||||
|
||||
/** |
||||
* A default adapter that if returned in {@link TypeAdapter#adapt(int, Object)}, will result |
||||
* in the default type adaption. |
||||
*/ |
||||
public static final Object DEFAULT = new Object(); |
||||
|
||||
/** |
||||
* Adapt an object from V8 to Java. |
||||
* |
||||
* If the value is a V8Value (V8Object) then it will be released after |
||||
* this method is called. If you wish to retain the object, call |
||||
* ((V8Value)value).twin(); |
||||
* |
||||
* @param type The Type of the object to be adapted. |
||||
* @param value The V8 Object to be converted. |
||||
* @return The adapted Java Object or {@link TypeAdapter#DEFAULT} for the default conversion. |
||||
*/ |
||||
public Object adapt(int type, Object value); |
||||
|
||||
} |
@ -1,73 +0,0 @@
|
||||
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(); |
||||
} |
||||
|
||||
} |
@ -1,253 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import java.util.LinkedList; |
||||
|
||||
import com.eclipsesource.v8.JavaVoidCallback; |
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
|
||||
/** |
||||
* Executes a JS Script on a new V8 runtime in its own thread, and once finished, |
||||
* will optionally wait on a message queue. If the executor is *not* long running, |
||||
* when the JS Script finishes, the executor will shutdown. If the executor |
||||
* *is* long running, the the script will execute, and when finished, the executor |
||||
* will wait for messages to arrive. When messages arrive, the messageHandler |
||||
* will be invoked with the contents of the message. |
||||
* |
||||
* Executors can be shutdown in two different ways. forceTermination() will |
||||
* stop any executing scripts and immediately terminate the executor. shutdown() |
||||
* will indicate that the executor should shutdown, but this will only happen |
||||
* once any scripts finish executing and the message queue becomes empty. |
||||
*/ |
||||
public class V8Executor extends Thread { |
||||
|
||||
private final String script; |
||||
private V8 runtime; |
||||
private String result; |
||||
private volatile boolean terminated = false; |
||||
private volatile boolean shuttingDown = false; |
||||
private volatile boolean forceTerminating = false; |
||||
private Exception exception = null; |
||||
private LinkedList<String[]> messageQueue = new LinkedList<String[]>(); |
||||
private boolean longRunning; |
||||
private String messageHandler; |
||||
|
||||
/** |
||||
* Create a new executor and execute the given script on it. Once |
||||
* the script has finished executing, the executor can optionally |
||||
* wait on a message queue. |
||||
* |
||||
* @param script The script to execute on this executor. |
||||
* @param longRunning True to indicate that this executor should be longRunning. |
||||
* @param messageHandler The name of the message handler that should be notified |
||||
* when messages are delivered. |
||||
*/ |
||||
public V8Executor(final String script, final boolean longRunning, final String messageHandler) { |
||||
this.script = script; |
||||
this.longRunning = longRunning; |
||||
this.messageHandler = messageHandler; |
||||
} |
||||
|
||||
/** |
||||
* Create a new executor and execute the given script on it. |
||||
* |
||||
* @param script The script to execute on this executor. |
||||
*/ |
||||
public V8Executor(final String script) { |
||||
this(script, false, null); |
||||
} |
||||
|
||||
/** |
||||
* Override to provide a custom setup for this V8 runtime. |
||||
* This method can be overridden to configure the V8 runtime, |
||||
* for example, to add callbacks or to add some additional |
||||
* functionality to the global scope. |
||||
* |
||||
* @param runtime The runtime to configure. |
||||
*/ |
||||
protected void setup(final V8 runtime) { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Gets the result of the JavaScript that was executed |
||||
* on this executor. |
||||
* |
||||
* @return The result of the JS Script that was executed on |
||||
* this executor. |
||||
*/ |
||||
public String getResult() { |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Posts a message to the receiver to be processed by the executor |
||||
* and sent to the V8 runtime via the messageHandler. |
||||
* |
||||
* @param message The message to send to the messageHandler |
||||
*/ |
||||
public void postMessage(final String... message) { |
||||
synchronized (this) { |
||||
messageQueue.add(message); |
||||
notify(); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.lang.Thread#run() |
||||
*/ |
||||
@Override |
||||
public void run() { |
||||
synchronized (this) { |
||||
runtime = V8.createV8Runtime(); |
||||
runtime.registerJavaMethod(new ExecutorTermination(), "__j2v8__checkThreadTerminate"); |
||||
setup(runtime); |
||||
} |
||||
try { |
||||
if (!forceTerminating) { |
||||
Object scriptResult = runtime.executeScript("__j2v8__checkThreadTerminate();\n" + script, getName(), -1); |
||||
if (scriptResult != null) { |
||||
result = scriptResult.toString(); |
||||
} |
||||
if (scriptResult instanceof Releasable) { |
||||
((Releasable) scriptResult).release(); |
||||
} |
||||
} |
||||
while (!forceTerminating && longRunning) { |
||||
synchronized (this) { |
||||
if (messageQueue.isEmpty() && !shuttingDown) { |
||||
wait(); |
||||
} |
||||
if ((messageQueue.isEmpty() && shuttingDown) || forceTerminating) { |
||||
return; |
||||
} |
||||
} |
||||
if (!messageQueue.isEmpty()) { |
||||
String[] message = messageQueue.remove(0); |
||||
V8Array parameters = new V8Array(runtime); |
||||
V8Array strings = new V8Array(runtime); |
||||
try { |
||||
for (String string : message) { |
||||
strings.push(string); |
||||
} |
||||
parameters.push(strings); |
||||
runtime.executeVoidFunction(messageHandler, parameters); |
||||
} finally { |
||||
strings.close(); |
||||
parameters.close(); |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
exception = e; |
||||
} finally { |
||||
synchronized (this) { |
||||
if (runtime.getLocker().hasLock()) { |
||||
runtime.close(); |
||||
runtime = null; |
||||
} |
||||
terminated = true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determines if an exception was thrown during the JavaScript execution. |
||||
* |
||||
* @return True if an exception was thrown during the JavaScript execution, |
||||
* false otherwise. |
||||
*/ |
||||
public boolean hasException() { |
||||
return exception != null; |
||||
} |
||||
|
||||
/** |
||||
* Gets the exception that was thrown during the JavaScript execution. |
||||
* |
||||
* @return The exception that was thrown during the JavaScript execution, |
||||
* or null if no such exception was thrown. |
||||
*/ |
||||
public Exception getException() { |
||||
return exception; |
||||
} |
||||
|
||||
/** |
||||
* Determines if the executor has terminated. |
||||
* |
||||
* @return True if the executor has terminated, false otherwise. |
||||
*/ |
||||
public boolean hasTerminated() { |
||||
return terminated; |
||||
} |
||||
|
||||
/** |
||||
* Forces the executor to shutdown immediately. Any currently executing |
||||
* JavaScript will be interrupted and all outstanding messages will be |
||||
* ignored. |
||||
*/ |
||||
public void forceTermination() { |
||||
synchronized (this) { |
||||
forceTerminating = true; |
||||
shuttingDown = true; |
||||
if (runtime != null) { |
||||
runtime.terminateExecution(); |
||||
} |
||||
notify(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Indicates to the executor that it should shutdown. Any currently |
||||
* executing JavaScript will be allowed to finish, and any outstanding |
||||
* messages will be processed. Only once the message queue is empty, |
||||
* will the executor actually shtutdown. |
||||
*/ |
||||
public void shutdown() { |
||||
synchronized (this) { |
||||
shuttingDown = true; |
||||
notify(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns true if shutdown() or forceTermination() was called to |
||||
* shutdown this executor. |
||||
* |
||||
* @return True if shutdown() or forceTermination() was called, false otherwise. |
||||
*/ |
||||
public boolean isShuttingDown() { |
||||
return shuttingDown; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if forceTermination was called to shutdown |
||||
* this executor. |
||||
* |
||||
* @return True if forceTermination() was called, false otherwise. |
||||
*/ |
||||
public boolean isTerminating() { |
||||
return forceTerminating; |
||||
} |
||||
|
||||
class ExecutorTermination implements JavaVoidCallback { |
||||
@Override |
||||
public void invoke(final V8Object receiver, final V8Array parameters) { |
||||
if (forceTerminating) { |
||||
throw new RuntimeException("V8Thread Termination"); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,185 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8Value; |
||||
|
||||
/** |
||||
* A Map that maps V8Values to arbitrary Java Objects. |
||||
* Once stored in the map, the keys (V8Values) can be released |
||||
* as the map will handle their resource management for you. |
||||
* |
||||
* Once the map is no longer needed, it should be released. To |
||||
* tie a map to the lifecycle of a V8 runtime, it can be registered |
||||
* as a resource with V8.registerResource. |
||||
*/ |
||||
public class V8Map<V> implements Map<V8Value, V>, Releasable { |
||||
|
||||
private Map<V8Value, V> map; |
||||
private Map<V8Value, V8Value> twinMap; |
||||
|
||||
/** |
||||
* Creates a V8Map. |
||||
*/ |
||||
public V8Map() { |
||||
map = new HashMap<V8Value, V>(); |
||||
twinMap = new HashMap<V8Value, V8Value>(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.io.Closeable#close() |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
this.clear(); |
||||
} |
||||
|
||||
/** |
||||
* Releases all the resources associated with this map. A |
||||
* map can be used again once it's released, although |
||||
* if it's used again it should be released again. |
||||
*/ |
||||
@Override |
||||
@Deprecated |
||||
public void release() { |
||||
close(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#size() |
||||
*/ |
||||
@Override |
||||
public int size() { |
||||
return map.size(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#isEmpty() |
||||
*/ |
||||
@Override |
||||
public boolean isEmpty() { |
||||
return map.isEmpty(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#containsKey(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public boolean containsKey(final Object key) { |
||||
return map.containsKey(key); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#containsValue(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public boolean containsValue(final Object value) { |
||||
return map.containsValue(value); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#get(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V get(final Object key) { |
||||
return map.get(key); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#put(java.lang.Object, java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V put(final V8Value key, final V value) { |
||||
this.remove(key); |
||||
V8Value twin = key.twin(); |
||||
twinMap.put(twin, twin); |
||||
return map.put(twin, value); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#remove(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V remove(final Object key) { |
||||
V result = map.remove(key); |
||||
V8Value twin = twinMap.remove(key); |
||||
if (twin != null) { |
||||
twin.close(); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#putAll(java.util.Map) |
||||
*/ |
||||
@Override |
||||
public void putAll(final Map<? extends V8Value, ? extends V> m) { |
||||
for (java.util.Map.Entry<? extends V8Value, ? extends V> entry : m.entrySet()) { |
||||
this.put(entry.getKey(), entry.getValue()); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#clear() |
||||
*/ |
||||
@Override |
||||
public void clear() { |
||||
map.clear(); |
||||
for (V8Value V8Value : twinMap.keySet()) { |
||||
V8Value.close(); |
||||
} |
||||
twinMap.clear(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#keySet() |
||||
*/ |
||||
@Override |
||||
public Set<V8Value> keySet() { |
||||
return map.keySet(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#values() |
||||
*/ |
||||
@Override |
||||
public Collection<V> values() { |
||||
return map.values(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#entrySet() |
||||
*/ |
||||
@Override |
||||
public Set<java.util.Map.Entry<V8Value, V>> entrySet() { |
||||
return map.entrySet(); |
||||
} |
||||
|
||||
} |
@ -1,703 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2014 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.Hashtable; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Map.Entry; |
||||
|
||||
import com.eclipsesource.v8.Releasable; |
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8ArrayBuffer; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.eclipsesource.v8.V8TypedArray; |
||||
import com.eclipsesource.v8.V8Value; |
||||
|
||||
/** |
||||
* A set of static helper methods to convert V8Objects / V8Arrays to |
||||
* java.util Maps and Lists and back again. These conversions |
||||
* perform a deep copy. |
||||
*/ |
||||
public class V8ObjectUtils { |
||||
|
||||
private static final Object IGNORE = new Object(); |
||||
private static final TypeAdapter DEFAULT_TYPE_ADAPTER = new DefaultTypeAdapter(); |
||||
|
||||
/** |
||||
* Create a Java Object from a result from V8. V8 can return |
||||
* basic Java types, or V8Values (V8Object, V8Array, etc...). This method |
||||
* will attempt to convert the result into a pure Java object using a |
||||
* deep copy. |
||||
* |
||||
* If the input is basic Java type (Integer, Double, Boolean, String) |
||||
* it will be returned. If the input is a V8Value, it will be converted. |
||||
* |
||||
* All elements in the V8Object are released after they are accessed. |
||||
* However, the root object itself is not released. |
||||
* |
||||
* @param v8Object The input to convert. |
||||
* @return A Java object representing the input. |
||||
*/ |
||||
public static Object getValue(final Object v8Object) { |
||||
return getValue(v8Object, DEFAULT_TYPE_ADAPTER); |
||||
} |
||||
|
||||
/** |
||||
* Create a Java Object from a result from V8 using a {@link TypeAdapter} to convert |
||||
* objects. V8 can return basic Java types or V8Values (V8Object, V8Array, etc...). This |
||||
* method will attempt to convert the result into a pure Java object using |
||||
* a deep copy. |
||||
* |
||||
* If the input is basic Java type (Integer, Double, Boolean, String) |
||||
* it will be returned. If the input is a V8Value, it will be converted. |
||||
* |
||||
* All elements in the V8Object are released after they are accessed. |
||||
* However, the root object itself is not released. |
||||
* |
||||
* @param v8Object The input to convert. |
||||
* @param adapter The {@link TypeAdapter} to use for the object conversions. |
||||
* @return A Java object representing the input. |
||||
*/ |
||||
public static Object getValue(final Object v8Object, final TypeAdapter adapter) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
try { |
||||
if (v8Object instanceof V8Value) { |
||||
int type = ((V8Value) v8Object).getV8Type(); |
||||
return getValue(v8Object, type, cache, adapter); |
||||
} else { |
||||
return v8Object; |
||||
} |
||||
} finally { |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates a Map from a V8Object using a deep copy. All elements |
||||
* in the V8Object are released after they are accessed. However, the root |
||||
* object itself is not released. |
||||
* |
||||
* @param object The root of the V8Object graph. |
||||
* |
||||
* @return A map representing a deep copy of the V8Object rooted at 'object'. |
||||
*/ |
||||
public static Map<String, ? super Object> toMap(final V8Object object) { |
||||
return toMap(object, DEFAULT_TYPE_ADAPTER); |
||||
} |
||||
|
||||
/** |
||||
* Creates a Map from a V8Object using a deep copy and a TypeAdapter to handle |
||||
* type conversions. All elements in the V8Object are released after they are accessed. |
||||
* However, the root object itself is not released. |
||||
* |
||||
* @param object The root of the V8Object graph. |
||||
* @param adapter The {@link TypeAdapter} to use for the object conversions. |
||||
* |
||||
* @return A map representing a deep copy of the V8Object rooted at 'object'. |
||||
*/ |
||||
public static Map<String, ? super Object> toMap(final V8Object object, final TypeAdapter adapter) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
try { |
||||
return toMap(object, cache, adapter); |
||||
} finally { |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates a List from a V8Array using a deep copy. All elements |
||||
* in the V8Array are released after they are accessed. However, the root |
||||
* array itself is not released. |
||||
* |
||||
* @param array The root of the V8Array graph. |
||||
* |
||||
* @return A list representing a deep copy of the V8Array rooted at 'array'. |
||||
*/ |
||||
public static List<? super Object> toList(final V8Array array) { |
||||
return toList(array, DEFAULT_TYPE_ADAPTER); |
||||
} |
||||
|
||||
/** |
||||
* Creates a List from a V8Array using a deep copy and a TypeAdapter to handle |
||||
* type conversions. All elements in the V8Array are released after they are accessed. |
||||
* However, the root array itself is not released. |
||||
* |
||||
* @param array The root of the V8Array graph. |
||||
* @param adapter The {@link TypeAdapter} to use for the object conversions. |
||||
* |
||||
* @return A list representing a deep copy of the V8Array rooted at 'array'. |
||||
*/ |
||||
public static List<? super Object> toList(final V8Array array, final TypeAdapter adapter) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
try { |
||||
return toList(array, cache, adapter); |
||||
} finally { |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Populates a Java array from a V8Array. The type of the array must be specified. |
||||
* Currently, only INTEGER, DOUBLE, BOOLEAN and STRING are supported. |
||||
* The V8Array must only contain elements of type 'arrayType'. The result |
||||
* can be optionally passed in as a parameter. |
||||
* |
||||
* This method will use J2V8's bulk array copy making it faster than iterating over |
||||
* all the elements in the array. |
||||
* |
||||
* @param array The V8Array to convert to a Java Array. |
||||
* @param arrayType The type of the V8Array to convert. |
||||
* @param result The array to use as the result. If null, a new array will be created. |
||||
* |
||||
* @return A Java array representing a V8Array. |
||||
*/ |
||||
public static Object getTypedArray(final V8Array array, final int arrayType, final Object result) { |
||||
int length = array.length(); |
||||
if (arrayType == V8Value.INTEGER) { |
||||
int[] intArray = (int[]) result; |
||||
if ((intArray == null) || (intArray.length < length)) { |
||||
intArray = new int[length]; |
||||
} |
||||
array.getIntegers(0, length, intArray); |
||||
return intArray; |
||||
} else if (arrayType == V8Value.DOUBLE) { |
||||
double[] doubleArray = (double[]) result; |
||||
if ((doubleArray == null) || (doubleArray.length < length)) { |
||||
doubleArray = new double[length]; |
||||
} |
||||
array.getDoubles(0, length, doubleArray); |
||||
return doubleArray; |
||||
} else if (arrayType == V8Value.BOOLEAN) { |
||||
boolean[] booleanArray = (boolean[]) result; |
||||
if ((booleanArray == null) || (booleanArray.length < length)) { |
||||
booleanArray = new boolean[length]; |
||||
} |
||||
array.getBooleans(0, length, booleanArray); |
||||
return booleanArray; |
||||
} else if (arrayType == V8Value.STRING) { |
||||
String[] stringArray = (String[]) result; |
||||
if ((stringArray == null) || (stringArray.length < length)) { |
||||
stringArray = new String[length]; |
||||
} |
||||
array.getStrings(0, length, stringArray); |
||||
return stringArray; |
||||
} else if (arrayType == V8Value.BYTE) { |
||||
byte[] byteArray = (byte[]) result; |
||||
if ((byteArray == null) || (byteArray.length < length)) { |
||||
byteArray = new byte[length]; |
||||
} |
||||
array.getBytes(0, length, byteArray); |
||||
return byteArray; |
||||
} |
||||
throw new RuntimeException("Unsupported bulk load type: " + arrayType); |
||||
} |
||||
|
||||
/** |
||||
* Creates a Java array from a V8Array. The type of the Array must be specified. |
||||
* Currently, only INTEGER, DOUBLE, BOOLEAN and STRING are supported. |
||||
* The V8Array must only contain elements of type 'arrayType'. |
||||
* |
||||
* This method will use J2V8's bulk array copy making it faster than iterating over |
||||
* all the elements in the array. |
||||
* |
||||
* @param array The V8Array to convert to a Java Array. |
||||
* @param arrayType The type of the V8Array to convert. |
||||
* |
||||
* @return A Java array representing a V8Array. |
||||
*/ |
||||
public static Object getTypedArray(final V8Array array, final int arrayType) { |
||||
int length = array.length(); |
||||
if (arrayType == V8Value.INTEGER) { |
||||
return array.getIntegers(0, length); |
||||
} else if (arrayType == V8Value.DOUBLE) { |
||||
return array.getDoubles(0, length); |
||||
} else if (arrayType == V8Value.BOOLEAN) { |
||||
return array.getBooleans(0, length); |
||||
} else if (arrayType == V8Value.STRING) { |
||||
return array.getStrings(0, length); |
||||
} |
||||
throw new RuntimeException("Unsupported bulk load type: " + arrayType); |
||||
} |
||||
|
||||
/** |
||||
* Creates a V8Object from a java.util.Map. This is a deep copy, so if the map |
||||
* contains other maps (or lists) they will also be converted. |
||||
* |
||||
* @param v8 The runtime on which to create the result. |
||||
* @param map The map to convert to a V8Object. |
||||
* |
||||
* @return A V8Object representing the map. |
||||
*/ |
||||
public static V8Object toV8Object(final V8 v8, final Map<String, ? extends Object> map) { |
||||
Map<Object, V8Value> cache = new Hashtable<Object, V8Value>(); |
||||
try { |
||||
return toV8Object(v8, map, cache).twin(); |
||||
} finally { |
||||
for (V8Value v8Object : cache.values()) { |
||||
v8Object.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates a V8Array from a java.util.List. This is a deep copy, so if the list |
||||
* contains other lists (or maps) they will also be converted. |
||||
* |
||||
* @param v8 The runtime on which to create the result. |
||||
* @param list The list to convert to a V8Array. |
||||
* |
||||
* @return A V8Array representing the list. |
||||
*/ |
||||
public static V8Array toV8Array(final V8 v8, final List<? extends Object> list) { |
||||
Map<Object, V8Value> cache = new Hashtable<Object, V8Value>(); |
||||
try { |
||||
return toV8Array(v8, list, cache).twin(); |
||||
} finally { |
||||
for (V8Value v8Object : cache.values()) { |
||||
v8Object.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns an object usable with a V8 Runtime which represents |
||||
* the parameter 'value'. If 'value' is an Integer, Boolean, Double |
||||
* or String, then 'value' is simply returned as these are directly |
||||
* usable on V8. If 'value' is a map / list, then it's converted to |
||||
* a V8Object / V8Array first. |
||||
* |
||||
* If the result is a V8Value, it must be released. |
||||
* |
||||
* @param v8 The runtime on which to create V8Values. |
||||
* @param value The value to convert to an object usable with V8 |
||||
* |
||||
* @return An object which can be used directly with a V8 runtime. |
||||
*/ |
||||
public static Object getV8Result(final V8 v8, final Object value) { |
||||
if (value == null) { |
||||
return null; |
||||
} |
||||
Map<Object, V8Value> cache = new Hashtable<Object, V8Value>(); |
||||
try { |
||||
Object result = getV8Result(v8, value, cache); |
||||
if (result instanceof V8Value) { |
||||
return ((V8Value) result).twin(); |
||||
} |
||||
return result; |
||||
} finally { |
||||
for (V8Value v8Object : cache.values()) { |
||||
v8Object.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Pushes a Java Object to a V8Array by first converting it to a V8Value if needed. |
||||
* If the value is a boxed primitive, then the primitive will be pushed. If the object |
||||
* is a Map / List then a deep copy will be performed, converting the object to a |
||||
* V8Object / V8Array first. |
||||
* |
||||
* @param v8 The runtime on which to create any needed V8Values. |
||||
* @param array The array to push the elements to. |
||||
* @param value The value to push to the array. |
||||
*/ |
||||
public static void pushValue(final V8 v8, final V8Array array, final Object value) { |
||||
Map<Object, V8Value> cache = new Hashtable<Object, V8Value>(); |
||||
try { |
||||
pushValue(v8, array, value, cache); |
||||
} finally { |
||||
for (V8Value v8Object : cache.values()) { |
||||
v8Object.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets a Java Object representing the value at the given index in the V8Array. |
||||
* If the value is a primitive (int, boolean or double) then a boxed instance |
||||
* is returned. If the value is a String, then a String is returned. If |
||||
* the value is a V8Object or V8Array, then a Map or List is returned. |
||||
* |
||||
* @param array The array on which to lookup the value. The array is not |
||||
* released. |
||||
* @param index The index whose element to lookup. |
||||
* |
||||
* @return A Java Object representing the value at a given index. |
||||
*/ |
||||
public static Object getValue(final V8Array array, final int index) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
Object object = null; |
||||
int type = V8Value.UNDEFINED; |
||||
try { |
||||
object = array.get(index); |
||||
type = array.getType(index); |
||||
Object result = getValue(object, type, cache, DEFAULT_TYPE_ADAPTER); |
||||
if ((result == object) && (result instanceof V8Value)) { |
||||
return ((V8Value) result).twin(); |
||||
} |
||||
return result; |
||||
} finally { |
||||
if (object instanceof Releasable) { |
||||
((Releasable) object).release(); |
||||
} |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets a Java Object representing the value at the given index in the V8Array. |
||||
* A TypeAdapter is used to convert values from V8Objects to Java Objects. |
||||
* If the value is a primitive (int, boolean or double) then a boxed instance |
||||
* is returned. If the value is a String, then a String is returned. If |
||||
* the value is a V8Object or V8Array, then a Map or List is returned. |
||||
* |
||||
* @param array The array on which to lookup the value. The array is not |
||||
* released. |
||||
* @param index The index whose element to lookup. |
||||
* @param adapter The {@link TypeAdapter} to use for the object conversions. |
||||
* |
||||
* @return A Java Object representing the value at a given index. |
||||
*/ |
||||
public static Object getValue(final V8Array array, final int index, final TypeAdapter adapter) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
Object object = null; |
||||
int type = V8Value.UNDEFINED; |
||||
try { |
||||
object = array.get(index); |
||||
type = array.getType(index); |
||||
Object result = getValue(object, type, cache, adapter); |
||||
if ((result == object) && (result instanceof V8Value)) { |
||||
return ((V8Value) result).twin(); |
||||
} |
||||
return result; |
||||
} finally { |
||||
if (object instanceof Releasable) { |
||||
((Releasable) object).release(); |
||||
} |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets a Java Object representing the value with the given key in the V8Object. |
||||
* If the value is a primitive (int, boolean or double) then a boxed instance |
||||
* is returned. If the value is a String, then a String is returned. If |
||||
* the value is a V8Object or V8Array, then a Map or List is returned. |
||||
* |
||||
* @param object The object on which to lookup the value. The object is not |
||||
* released. |
||||
* @param key The key to use to lookup the value. |
||||
* |
||||
* @return A Java Object representing the value at a given key. |
||||
*/ |
||||
public static Object getValue(final V8Object object, final String key) { |
||||
return getValue(object, key, DEFAULT_TYPE_ADAPTER); |
||||
} |
||||
|
||||
/** |
||||
* Gets a Java Object representing the value with the given key in the V8Object. |
||||
* A TypeAdapter is used to convert values from V8Objects to Java Objects. |
||||
* If the value is a primitive (int, boolean or double) then a boxed instance |
||||
* is returned. If the value is a String, then a String is returned. If |
||||
* the value is a V8Object or V8Array, then a Map or List is returned. |
||||
* |
||||
* @param v8Object The object on which to lookup the value. The object is not |
||||
* released. |
||||
* @param key The key to use to lookup the value. |
||||
* @param adapter The {@link TypeAdapter} to use for the object conversions. |
||||
* |
||||
* @return A Java Object representing the value at a given key. |
||||
*/ |
||||
public static Object getValue(final V8Object v8Object, final String key, final TypeAdapter adapter) { |
||||
V8Map<Object> cache = new V8Map<Object>(); |
||||
Object object = null; |
||||
int type = V8Value.UNDEFINED; |
||||
try { |
||||
object = v8Object.get(key); |
||||
type = v8Object.getType(key); |
||||
Object result = getValue(object, type, cache, adapter); |
||||
if ((result == object) && (result instanceof V8Value)) { |
||||
return ((V8Value) result).twin(); |
||||
} |
||||
return result; |
||||
} finally { |
||||
if (object instanceof Releasable) { |
||||
((Releasable) object).release(); |
||||
} |
||||
cache.close(); |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private static Map<String, ? super Object> toMap(final V8Object v8Object, final V8Map<Object> cache, final TypeAdapter adapter) { |
||||
if (v8Object == null) { |
||||
return Collections.emptyMap(); |
||||
} |
||||
if (cache.containsKey(v8Object)) { |
||||
return (Map<String, ? super Object>) cache.get(v8Object); |
||||
} |
||||
Map<String, ? super Object> result = new V8PropertyMap<Object>(); |
||||
cache.put(v8Object, result); |
||||
String[] keys = v8Object.getKeys(); |
||||
for (String key : keys) { |
||||
Object object = null; |
||||
int type = V8Value.UNDEFINED; |
||||
try { |
||||
object = v8Object.get(key); |
||||
type = v8Object.getType(key); |
||||
Object value = getValue(object, type, cache, adapter); |
||||
if (value != IGNORE) { |
||||
result.put(key, value); |
||||
} |
||||
} finally { |
||||
if (object instanceof Releasable) { |
||||
((Releasable) object).release(); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private static List<? super Object> toList(final V8Array array, final V8Map<Object> cache, final TypeAdapter adapter) { |
||||
if (array == null) { |
||||
return Collections.emptyList(); |
||||
} |
||||
if (cache.containsKey(array)) { |
||||
return (List<? super Object>) cache.get(array); |
||||
} |
||||
List<? super Object> result = new ArrayList<Object>(); |
||||
cache.put(array, result); |
||||
for (int i = 0; i < array.length(); i++) { |
||||
Object object = null; |
||||
int type = V8Value.UNDEFINED; |
||||
try { |
||||
object = array.get(i); |
||||
type = array.getType(i); |
||||
Object value = getValue(object, type, cache, adapter); |
||||
if (value != IGNORE) { |
||||
result.add(value); |
||||
} |
||||
} finally { |
||||
if (object instanceof Releasable) { |
||||
((Releasable) object).release(); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static V8TypedArray toV8TypedArray(final V8 v8, final TypedArray typeArray, final Map<Object, V8Value> cache) { |
||||
if (cache.containsKey(typeArray)) { |
||||
return (V8TypedArray) cache.get(typeArray); |
||||
} |
||||
V8TypedArray result = typeArray.getV8TypedArray(); |
||||
cache.put(typeArray, result); |
||||
return result; |
||||
} |
||||
|
||||
private static V8ArrayBuffer toV8ArrayBuffer(final V8 v8, final ArrayBuffer arrayBuffer, final Map<Object, V8Value> cache) { |
||||
if (cache.containsKey(arrayBuffer)) { |
||||
return (V8ArrayBuffer) cache.get(arrayBuffer); |
||||
} |
||||
V8ArrayBuffer result = arrayBuffer.getV8ArrayBuffer(); |
||||
cache.put(arrayBuffer, result); |
||||
return result; |
||||
} |
||||
|
||||
private static V8Object toV8Object(final V8 v8, final Map<String, ? extends Object> map, final Map<Object, V8Value> cache) { |
||||
if (cache.containsKey(map)) { |
||||
return (V8Object) cache.get(map); |
||||
} |
||||
V8Object result = new V8Object(v8); |
||||
cache.put(map, result); |
||||
try { |
||||
for (Entry<String, ? extends Object> entry : map.entrySet()) { |
||||
setValue(v8, result, entry.getKey(), entry.getValue(), cache); |
||||
} |
||||
} catch (IllegalStateException e) { |
||||
result.close(); |
||||
throw e; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static V8Array toV8Array(final V8 v8, final List<? extends Object> list, final Map<Object, V8Value> cache) { |
||||
if (cache.containsKey(new ListWrapper(list))) { |
||||
return (V8Array) cache.get(new ListWrapper(list)); |
||||
} |
||||
V8Array result = new V8Array(v8); |
||||
cache.put(new ListWrapper(list), result); |
||||
try { |
||||
for (int i = 0; i < list.size(); i++) { |
||||
Object value = list.get(i); |
||||
pushValue(v8, result, value, cache); |
||||
} |
||||
} catch (IllegalStateException e) { |
||||
result.close(); |
||||
throw e; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private static Object getV8Result(final V8 v8, final Object value, final Map<Object, V8Value> cache) { |
||||
if (cache.containsKey(value)) { |
||||
return cache.get(value); |
||||
} |
||||
if (value instanceof Map<?, ?>) { |
||||
return toV8Object(v8, (Map<String, ? extends Object>) value, cache); |
||||
} else if (value instanceof List<?>) { |
||||
return toV8Array(v8, (List<? extends Object>) value, cache); |
||||
} else if (value instanceof TypedArray) { |
||||
return toV8TypedArray(v8, (TypedArray) value, cache); |
||||
} else if (value instanceof ArrayBuffer) { |
||||
return toV8ArrayBuffer(v8, (ArrayBuffer) value, cache); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "resource" }) |
||||
private static void pushValue(final V8 v8, final V8Array result, final Object value, final Map<Object, V8Value> cache) { |
||||
if (value == null) { |
||||
result.pushUndefined(); |
||||
} else if (value instanceof Integer) { |
||||
result.push(value); |
||||
} else if (value instanceof Long) { |
||||
result.push(new Double((Long) value)); |
||||
} else if (value instanceof Double) { |
||||
result.push(value); |
||||
} else if (value instanceof Float) { |
||||
result.push(value); |
||||
} else if (value instanceof String) { |
||||
result.push((String) value); |
||||
} else if (value instanceof Boolean) { |
||||
result.push(value); |
||||
} else if (value instanceof TypedArray) { |
||||
V8TypedArray v8TypedArray = toV8TypedArray(v8, (TypedArray) value, cache); |
||||
result.push(v8TypedArray); |
||||
} else if (value instanceof ArrayBuffer) { |
||||
V8ArrayBuffer v8ArrayBuffer = toV8ArrayBuffer(v8, (ArrayBuffer) value, cache); |
||||
result.push(v8ArrayBuffer); |
||||
} else if (value instanceof V8Value) { |
||||
result.push((V8Value) value); |
||||
} else if (value instanceof Map) { |
||||
V8Object object = toV8Object(v8, (Map) value, cache); |
||||
result.push(object); |
||||
} else if (value instanceof List) { |
||||
V8Array array = toV8Array(v8, (List) value, cache); |
||||
result.push(array); |
||||
} else { |
||||
throw new IllegalStateException("Unsupported Object of type: " + value.getClass()); |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "resource" }) |
||||
private static void setValue(final V8 v8, final V8Object result, final String key, final Object value, final Map<Object, V8Value> cache) { |
||||
if (value == null) { |
||||
result.addUndefined(key); |
||||
} else if (value instanceof Integer) { |
||||
result.add(key, (Integer) value); |
||||
} else if (value instanceof Long) { |
||||
result.add(key, (Long) value); |
||||
} else if (value instanceof Double) { |
||||
result.add(key, (Double) value); |
||||
} else if (value instanceof Float) { |
||||
result.add(key, (Float) value); |
||||
} else if (value instanceof String) { |
||||
result.add(key, (String) value); |
||||
} else if (value instanceof Boolean) { |
||||
result.add(key, (Boolean) value); |
||||
} else if (value instanceof TypedArray) { |
||||
V8TypedArray v8TypedArray = toV8TypedArray(v8, (TypedArray) value, cache); |
||||
result.add(key, v8TypedArray); |
||||
} else if (value instanceof ArrayBuffer) { |
||||
V8ArrayBuffer v8ArrayBuffer = toV8ArrayBuffer(v8, (ArrayBuffer) value, cache); |
||||
result.add(key, v8ArrayBuffer); |
||||
} else if (value instanceof V8Value) { |
||||
result.add(key, (V8Value) value); |
||||
} else if (value instanceof Map) { |
||||
V8Object object = toV8Object(v8, (Map) value, cache); |
||||
result.add(key, object); |
||||
} else if (value instanceof List) { |
||||
V8Array array = toV8Array(v8, (List) value, cache); |
||||
result.add(key, array); |
||||
} else { |
||||
throw new IllegalStateException("Unsupported Object of type: " + value.getClass()); |
||||
} |
||||
} |
||||
|
||||
private static Object getValue(final Object value, final int valueType, final V8Map<Object> cache, final TypeAdapter adapter) { |
||||
Object adapterResult = adapter.adapt(valueType, value); |
||||
if (TypeAdapter.DEFAULT != adapterResult) { |
||||
return adapterResult; |
||||
} |
||||
switch (valueType) { |
||||
case V8Value.INTEGER: |
||||
case V8Value.DOUBLE: |
||||
case V8Value.BOOLEAN: |
||||
case V8Value.STRING: |
||||
return value; |
||||
case V8Value.V8_FUNCTION: |
||||
return IGNORE; |
||||
case V8Value.V8_ARRAY_BUFFER: |
||||
return new ArrayBuffer((V8ArrayBuffer) value); |
||||
case V8Value.V8_TYPED_ARRAY: |
||||
return new TypedArray((V8TypedArray) value); |
||||
case V8Value.V8_ARRAY: |
||||
return toList((V8Array) value, cache, adapter); |
||||
case V8Value.V8_OBJECT: |
||||
return toMap((V8Object) value, cache, adapter); |
||||
case V8Value.NULL: |
||||
return null; |
||||
case V8Value.UNDEFINED: |
||||
return V8.getUndefined(); |
||||
default: |
||||
throw new IllegalStateException("Cannot convert type " + V8Value.getStringRepresentation(valueType)); |
||||
} |
||||
} |
||||
|
||||
private V8ObjectUtils() { |
||||
|
||||
} |
||||
|
||||
static class DefaultTypeAdapter implements TypeAdapter { |
||||
@Override |
||||
public Object adapt(final int type, final Object value) { |
||||
return TypeAdapter.DEFAULT; |
||||
} |
||||
} |
||||
|
||||
static class ListWrapper { |
||||
private List<? extends Object> list; |
||||
|
||||
public ListWrapper(final List<? extends Object> list) { |
||||
this.list = list; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object obj) { |
||||
if (obj instanceof ListWrapper) { |
||||
return ((ListWrapper) obj).list == list; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return System.identityHashCode(list); |
||||
} |
||||
} |
||||
} |
@ -1,176 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import java.util.AbstractMap.SimpleEntry; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.HashSet; |
||||
import java.util.Hashtable; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* A custom map is needed because the existing HashMaps |
||||
* do not allow self containment, and Hashtables do not |
||||
* allow nulls as values. |
||||
* |
||||
* This class is not considered API. |
||||
*/ |
||||
class V8PropertyMap<V> implements Map<String, V> { |
||||
|
||||
private Hashtable<String, V> map = new Hashtable<String, V>(); |
||||
private Set<String> nulls = new HashSet<String>(); |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#size() |
||||
*/ |
||||
@Override |
||||
public int size() { |
||||
return map.size() + nulls.size(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#isEmpty() |
||||
*/ |
||||
@Override |
||||
public boolean isEmpty() { |
||||
return map.isEmpty() && nulls.isEmpty(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#containsKey(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public boolean containsKey(final Object key) { |
||||
return map.containsKey(key) || nulls.contains(key); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#containsValue(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public boolean containsValue(final Object value) { |
||||
if ((value == null) && !nulls.isEmpty()) { |
||||
return true; |
||||
} else if (value == null) { |
||||
return false; |
||||
} |
||||
return map.containsValue(value); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#get(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V get(final Object key) { |
||||
if (nulls.contains(key)) { |
||||
return null; |
||||
} |
||||
return map.get(key); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#put(java.lang.Object, java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V put(final String key, final V value) { |
||||
if (value == null) { |
||||
if (map.containsKey(key)) { |
||||
map.remove(key); |
||||
} |
||||
nulls.add(key); |
||||
return null; |
||||
} |
||||
if (nulls.contains(key)) { |
||||
nulls.remove(key); |
||||
} |
||||
return map.put(key, value); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#remove(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public V remove(final Object key) { |
||||
if (nulls.contains(key)) { |
||||
nulls.remove(key); |
||||
return null; |
||||
} |
||||
return map.remove(key); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#putAll(java.util.Map) |
||||
*/ |
||||
@Override |
||||
public void putAll(final Map<? extends String, ? extends V> m) { |
||||
for (Entry<? extends String, ? extends V> entry : m.entrySet()) { |
||||
this.put(entry.getKey(), entry.getValue()); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#clear() |
||||
*/ |
||||
@Override |
||||
public void clear() { |
||||
map.clear(); |
||||
nulls.clear(); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#keySet() |
||||
*/ |
||||
@Override |
||||
public Set<String> keySet() { |
||||
HashSet<String> result = new HashSet<String>(map.keySet()); |
||||
result.addAll(nulls); |
||||
return result; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#values() |
||||
*/ |
||||
@Override |
||||
public Collection<V> values() { |
||||
ArrayList<V> result = new ArrayList<V>(map.values()); |
||||
for (int i = 0; i < nulls.size(); i++) { |
||||
result.add(null); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.util.Map#entrySet() |
||||
*/ |
||||
@Override |
||||
public Set<Entry<String, V>> entrySet() { |
||||
HashSet<Entry<String, V>> result = new HashSet<Map.Entry<String, V>>(map.entrySet()); |
||||
for (String nullKey : nulls) { |
||||
result.add(new SimpleEntry<String, V>(nullKey, null)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import com.eclipsesource.v8.V8; |
||||
|
||||
/** |
||||
* Classes can implement this interface to execute arbitrary code on |
||||
* isolated V8 runtime on its own thread. Instances of classes that |
||||
* implement this interface can be passed to V8Thread. |
||||
*/ |
||||
public interface V8Runnable { |
||||
|
||||
/** |
||||
* Execute the code on the provided runtime. |
||||
* |
||||
* @param runtime The V8 runtime assigned to this runnable. |
||||
*/ |
||||
public void run(final V8 runtime); |
||||
|
||||
} |
@ -1,57 +0,0 @@
|
||||
/******************************************************************************* |
||||
* Copyright (c) 2015 EclipseSource and others. |
||||
* All rights reserved. This program and the accompanying materials |
||||
* are made available under the terms of the Eclipse Public License v1.0 |
||||
* which accompanies this distribution, and is available at |
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* |
||||
* Contributors: |
||||
* EclipseSource - initial API and implementation |
||||
******************************************************************************/ |
||||
package com.eclipsesource.v8.utils; |
||||
|
||||
import com.eclipsesource.v8.V8; |
||||
|
||||
/** |
||||
* A Thread with its own V8 runtime. The thread will create a runtime, |
||||
* and execute a runnable on that runtime. When the thread ends, |
||||
* the runtime will be released. |
||||
* |
||||
* It's suggested that you *DO NOT* release the lock on the runtime. |
||||
* If the lock is released, you will need to ensure that the runtime |
||||
* is properly released. |
||||
*/ |
||||
public class V8Thread extends Thread { |
||||
|
||||
private final V8Runnable target; |
||||
private V8 runtime; |
||||
|
||||
/** |
||||
* Create as new Thread with its own V8Runtime. |
||||
* |
||||
* @param target The code to execute with the given runtime. |
||||
*/ |
||||
public V8Thread(final V8Runnable target) { |
||||
this.target = target; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see java.lang.Thread#run() |
||||
*/ |
||||
@Override |
||||
public void run() { |
||||
runtime = V8.createV8Runtime(); |
||||
try { |
||||
target.run(runtime); |
||||
} finally { |
||||
synchronized (this) { |
||||
if (runtime.getLocker().hasLock()) { |
||||
runtime.close(); |
||||
runtime = null; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue