Skip to content

Commit

Permalink
Javet v0.8.1 (#13)
Browse files Browse the repository at this point in the history
* Enabled declarative function interception
* Enabled custom object converter in function callback
* Added ``allowEval`` to ``JavetEngineConfig``
* Refactored built-in module API for Node.js mode
  • Loading branch information
caoccao authored Apr 4, 2021
1 parent a1140c1 commit d704ad7
Show file tree
Hide file tree
Showing 86 changed files with 3,626 additions and 2,593 deletions.
23 changes: 15 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
Javet
=====

|Maven Central|
|Maven Central| |Gitter Chatroom|

.. |Maven Central| image:: https://img.shields.io/maven-central/v/com.caoccao.javet/javet.svg
:target: https://search.maven.org/search?q=g:com.caoccao.javet

.. |Gitter Chatroom| image:: https://badges.gitter.im/caoccao/Javet.svg
:target: https://gitter.im/caoccao/Javet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge

Javet is Java + V8 (JAVa + V + EighT). It is an awesome way of embedding Node.js and V8 in Java.

If you like my work, please **Star** this project. And, you may follow me `@sjtucaocao <https://twitter.com/sjtucaocao>`_ or visit http://caoccao.blogspot.com/.
If you like my work, please **Star** this project. And, you may follow me `@sjtucaocao <https://twitter.com/sjtucaocao>`_, or visit http://caoccao.blogspot.com/.

Major Features
==============

* Linux + Windows
* Node.js ``14.16.0`` + V8 ``v8.9.255``
* 🐧Linux + 🖥️Windows
* Node.js ``v14.16.0`` + V8 ``v8.9.255``
* Dynamic switch between Node.js and V8
* Exposure of the majority of V8 API in JVM
* JS function interception
Expand All @@ -37,29 +40,29 @@ Maven
<dependency>
<groupId>com.caoccao.javet</groupId>
<artifactId>javet</artifactId>
<version>0.8.0</version>
<version>0.8.1</version>
</dependency>
Gradle Kotlin DSL
^^^^^^^^^^^^^^^^^

.. code-block:: kotlin
implementation("com.caoccao.javet:javet:0.8.0")
implementation("com.caoccao.javet:javet:0.8.1")
Gradle Groovy DSL
^^^^^^^^^^^^^^^^^

.. code-block:: groovy
implementation 'com.caoccao.javet:javet:0.8.0'
implementation 'com.caoccao.javet:javet:0.8.1'
Hello Javet
-----------

.. code-block:: java
// Node Mode
// Node.js Mode
try (V8Runtime v8Runtime = V8Host.getNodeInstance().createV8Runtime()) {
System.out.println(v8Runtime.getExecutor("'Hello Javet'").executeString());
}
Expand All @@ -72,6 +75,10 @@ Hello Javet
Documents
=========

* Presentations

* `Javet Intro <https://docs.google.com/presentation/d/1lQ8xIHuywuE0ydqm2w6xq8OeQZO_WeTLYXW9bNflQb8/>`_

* `Development <docs/development/index.rst>`_

* `Build <docs/development/build.rst>`_
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ repositories {
}

group = "com.caoccao.javet"
version = "0.8.0"
version = "0.8.1"

repositories {
mavenCentral()
Expand Down
10 changes: 5 additions & 5 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ endif()
if(DEFINED V8_DIR)
list(APPEND includeDirs
${V8_DIR}/include)
list(APPEND importLibraries
v8_monolith)
list(APPEND importLibraries v8_monolith)
set(JAVET_LIB_TYPE "v8")
endif()
if(DEFINED NODE_DIR)
Expand Down Expand Up @@ -69,24 +68,25 @@ endforeach(importLibrary)
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(JAVET_LIB_PREFIX "libjavet")
set(JAVET_LIB_SYSTEM "windows")
add_library(Javet SHARED ${sourceFiles} "jni/javet.rc")
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
list(APPEND includeDirs $ENV{JAVA_HOME}/include/win32)
set_property(TARGET Javet APPEND_STRING PROPERTY LINK_FLAGS_RELEASE "")
set_property(TARGET Javet PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
if(DEFINED V8_DIR)
foreach(importLibrary ${importLibraries})
set_target_properties(${importLibrary} PROPERTIES IMPORTED_LOCATION ${V8_DIR}/out.gn/x64.release/obj/${importLibrary}.lib)
endforeach(importLibrary)
set_target_properties(v8_monolith PROPERTIES LINK_FLAGS "/WHOLEARCHIVE:v8_monolith.lib")
add_library(Javet SHARED ${sourceFiles} "jni/javet_resource_v8.rc")
endif()
if(DEFINED NODE_DIR)
foreach(importLibrary ${importLibraries})
set_target_properties(${importLibrary} PROPERTIES IMPORTED_LOCATION ${NODE_DIR}/out/release/lib/${importLibrary}.lib)
endforeach(importLibrary)
set_target_properties(libnode PROPERTIES LINK_FLAGS "/WHOLEARCHIVE:libnode.lib")
add_library(Javet SHARED ${sourceFiles} "jni/javet_resource_node.rc")
endif()
set_property(TARGET Javet APPEND_STRING PROPERTY LINK_FLAGS_RELEASE "")
set_property(TARGET Javet PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_link_libraries(Javet ${importLibraries})
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(JAVET_LIB_PREFIX "javet")
Expand Down
2 changes: 1 addition & 1 deletion cpp/build.cmd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@echo off
REM Usage for V8: build -DV8_DIR=C:\v8
REM Usage for Node: build -DNODE_DIR=C:\node
SET JAVET_VERSION=0.8.0
SET JAVET_VERSION=0.8.1
rd /s/q build
mkdir build
cd build
Expand Down
2 changes: 1 addition & 1 deletion cpp/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Usage for V8: build -DV8_DIR=~/v8
# Usage for Node: build -DNODE_DIR=~/node
JAVET_VERSION=0.8.0
JAVET_VERSION=0.8.1
rm -rf build
mkdir build
cd build
Expand Down
4 changes: 2 additions & 2 deletions cpp/jni/javet_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace Javet {
jmethodIDThrowableGetMessage = jniEnv->GetMethodID(jclassThrowable, "getMessage", "()Ljava/lang/String;");

jclassV8Runtime = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/interop/V8Runtime"));
jmethodIDV8RuntimeGetModule = jniEnv->GetMethodID(jclassV8Runtime, "getModule", "(Ljava/lang/String;)Lcom/caoccao/javet/values/reference/IV8Module;");
jmethodIDV8RuntimeGetV8Module = jniEnv->GetMethodID(jclassV8Runtime, "getV8Module", "(Ljava/lang/String;)Lcom/caoccao/javet/values/reference/IV8Module;");
}

V8MaybeLocalModule ModuleResolveCallback(
Expand All @@ -65,7 +65,7 @@ namespace Javet {
auto v8Runtime = V8Runtime::FromV8Context(v8Context);
FETCH_JNI_ENV(GlobalJavaVM);
jobject mIV8Module = jniEnv->CallObjectMethod(
v8Runtime->externalV8Runtime, jmethodIDV8RuntimeGetModule,
v8Runtime->externalV8Runtime, jmethodIDV8RuntimeGetV8Module,
Javet::Converter::ToJavaString(jniEnv, v8Context, specifier));
if (mIV8Module == nullptr) {
LOG_ERROR("ModuleResolveCallback: module " << *Javet::Converter::ToStdString(v8Context, specifier) << " not found");
Expand Down
2 changes: 1 addition & 1 deletion cpp/jni/javet_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Javet {
static jmethodID jmethodIDThrowableGetMessage;

static jclass jclassV8Runtime;
static jmethodID jmethodIDV8RuntimeGetModule;
static jmethodID jmethodIDV8RuntimeGetV8Module;

void Initialize(JNIEnv* jniEnv, JavaVM* javaVM);

Expand Down
110 changes: 110 additions & 0 deletions cpp/jni/javet_resource_node.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Chinese (Simplified, PRC) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED

#endif // Chinese (Simplified, PRC) resources
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// English (United States) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)

/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,8,1,0
PRODUCTVERSION 0,8,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000904b0"
BEGIN
VALUE "CompanyName", "caoccao.com"
VALUE "FileDescription", "caoccao.com"
VALUE "FileVersion", "0.8.1.0"
VALUE "InternalName", "libjavet-node-windows-x86_64.v.0.8.1.dll"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "libjavet-node-windows-x86_64.v.0.8.1.dll"
VALUE "ProductName", "Javet Windows"
VALUE "ProductVersion", "0.8.1.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x9, 1200
END
END

#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

12 changes: 6 additions & 6 deletions cpp/jni/javet.rc → cpp/jni/javet_resource_v8.rc
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,8,0,0
PRODUCTVERSION 0,8,0,0
FILEVERSION 0,8,1,0
PRODUCTVERSION 0,8,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -79,12 +79,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "caoccao.com"
VALUE "FileDescription", "caoccao.com"
VALUE "FileVersion", "0.8.0.0"
VALUE "InternalName", "javet-windows-x86_64.v.0.8.0.dll"
VALUE "FileVersion", "0.8.1.0"
VALUE "InternalName", "libjavet-v8-windows-x86_64.v.0.8.1.dll"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "javet-windows-x86_64.v.0.8.0.dll"
VALUE "OriginalFilename", "libjavet-v8-windows-x86_64.v.0.8.1.dll"
VALUE "ProductName", "Javet Windows"
VALUE "ProductVersion", "0.8.0.0"
VALUE "ProductVersion", "0.8.1.0"
END
END
BLOCK "VarFileInfo"
Expand Down
22 changes: 22 additions & 0 deletions docs/development/design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,26 @@ Multiple Javet engines are managed by Javet Engine Pool which works almost the s

Please refer to `Best Practices <best_practices.rst>`_ for detail.

Interception
============

Javet allows intercepting almost all V8 API so that JS code actually interacts with Java code behind the scene.

.. image:: ../resources/images/javet_interception.png?raw=true
:alt: Javet Interception

Sample code is available at `here <../turorial/manipulate_v8_function.rst>`_.

Cross-platform
==============

Javet packages all the libraries in a single jar file and automatically loads corresponding library per OS and JS runtime.

.. image:: ../resources/images/javet_cross_platform.png?raw=true
:alt: Javet Cross-platform

* Javet calculates the library file name from OS and JS runtime.
* Javet unpacks the library file from resource directory to system temporary directory.
* Javet loads the library using either default classloader or custom classloader.

[`Home <../../README.rst>`_] [`Development <index.rst>`_]
48 changes: 48 additions & 0 deletions docs/faq/how_to_think_in_javet.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
======================
How to Think in Javet?
======================

There are folks migrating projects from other libraries (e.g. J2V8) to Javet. Some experienced certain challenges which from Javet perspective required **Thinking in Javet**. So, how?

``V8Runtime`` and ``V8ValueGlobalObject``
=========================================

In Javet, ``V8Runtime`` and ``V8ValueGlobalObject`` are separate concepts.

``V8Runtime``
-------------

``V8Runtime`` is only a representative of the V8 isolate and V8 context. It has nothing to do with ``globalThis`` or ``window``. However, in few other libraries these concepts are mixed up.

``V8ValueGlobalObject``
-----------------------

As ``V8Runtime`` no longer represents ``globalThis`` or ``window``, ``V8ValueGlobalObject`` from ``V8Runtime.getGlobalObject()`` is the one.

If you want to access global objects or call top level functions, ``globalObject.get('...')`` and ``globalObject.invoke('...')`` are the Javet ways.

Executor and Execute
====================

In Javet, executing a script involves 2 steps.

1. Get the executor.
2. Call certain execute method of that executor.

This is quite different from the common practice of few other libraries where execute is just a 1-step thing.

Why? Javet intends to offer a builder pattern in the script execution. With an executor, application may do every other things before the actual execution. For instance: security check, enable / disable certain V8 features, hack the AST, set up interception, etc. The scope may be limited to that executor only. Also, the executor can be reused to avoid the duplicated resource loading overhead.

Declarative Function Interception
=================================

Javet offers an easy way of registering function interception in a declarative way. Just decorate a function of arbitrary object with ``@V8Function(name = "...")``, Javet is able to register it and that function will be called back from V8. Application is free from managing those tedious things like resource leakage, object lifecycle, type conversion, etc. Javet just handles that behind the scene and everything goes smoothly.

The coding experience is a little bit close to working with Spring Framework.

Learn from Unit Test
====================

Most of the Javet API is unit test coverted. Learning from Javet unit test is an express and effective way to Thinking in Javet.

[`Home <../../README.rst>`_] [`FAQ <index.rst>`_]
1 change: 1 addition & 0 deletions docs/faq/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FAQ

* `History with J2V8 <history_with_j2v8.rst>`_
* `Can Javet Support Mac? <can_javet_support_mac.rst>`_
* `How to Think in Javet? <how_to_think_in_javet.rst>`_
* `Can I Debug Javet in Chrome DevTools? <can_i_debug_javet_in_chrome_dev_tools.rst>`_
* `What is the Motivation? <what_is_the_motivation.rst>`_

Expand Down
Loading

0 comments on commit d704ad7

Please sign in to comment.