diff --git a/.gitignore b/.gitignore
index 20adb7c8a..59fda8d2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,8 @@ gradle-app.setting
# Package Files #
*.jar
+*.dll
+*.so
*.war
*.nar
*.ear
@@ -64,3 +66,13 @@ _build
# Node
**/node_modules
+
+# ------------------------------------------------------------------------------
+# Maven
+
+.classpath
+.project
+.settings
+pom.xml.releaseBackup
+release.properties
+target
diff --git a/LICENSE b/LICENSE
index e23ece2c8..d64569567 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,277 +1,202 @@
-Eclipse Public License - v 2.0
-
- THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
- PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
- OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
- a) in the case of the initial Contributor, the initial content
- Distributed under this Agreement, and
-
- b) in the case of each subsequent Contributor:
- i) changes to the Program, and
- ii) additions to the Program;
- where such changes and/or additions to the Program originate from
- and are Distributed by that particular Contributor. A Contribution
- "originates" from a Contributor if it was added to the Program by
- such Contributor itself or anyone acting on such Contributor's behalf.
- Contributions do not include changes or additions to the Program that
- are not Modified Works.
-
-"Contributor" means any person or entity that Distributes the Program.
-
-"Licensed Patents" mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions Distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement
-or any Secondary License (as applicable), including Contributors.
-
-"Derivative Works" shall mean any work, whether in Source Code or other
-form, that is based on (or derived from) the Program and for which the
-editorial revisions, annotations, elaborations, or other modifications
-represent, as a whole, an original work of authorship.
-
-"Modified Works" shall mean any work in Source Code or other form that
-results from an addition to, deletion from, or modification of the
-contents of the Program, including, for purposes of clarity any new file
-in Source Code form that contains any contents of the Program. Modified
-Works shall not include works that contain only declarations,
-interfaces, types, classes, structures, or files of the Program solely
-in each case in order to link to, bind by name, or subclass the Program
-or Modified Works thereof.
-
-"Distribute" means the acts of a) distributing or b) making available
-in any manner that enables the transfer of a copy.
-
-"Source Code" means the form of a Program preferred for making
-modifications, including but not limited to software source code,
-documentation source, and configuration files.
-
-"Secondary License" means either the GNU General Public License,
-Version 2.0, or any later versions of that license, including any
-exceptions or additional permissions as identified by the initial
-Contributor.
-
-2. GRANT OF RIGHTS
-
- a) Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free copyright
- license to reproduce, prepare Derivative Works of, publicly display,
- publicly perform, Distribute and sublicense the Contribution of such
- Contributor, if any, and such Derivative Works.
-
- b) Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free patent
- license under Licensed Patents to make, use, sell, offer to sell,
- import and otherwise transfer the Contribution of such Contributor,
- if any, in Source Code or other form. This patent license shall
- apply to the combination of the Contribution and the Program if, at
- the time the Contribution is added by the Contributor, such addition
- of the Contribution causes such combination to be covered by the
- Licensed Patents. The patent license shall not apply to any other
- combinations which include the Contribution. No hardware per se is
- licensed hereunder.
-
- c) Recipient understands that although each Contributor grants the
- licenses to its Contributions set forth herein, no assurances are
- provided by any Contributor that the Program does not infringe the
- patent or other intellectual property rights of any other entity.
- Each Contributor disclaims any liability to Recipient for claims
- brought by any other entity based on infringement of intellectual
- property rights or otherwise. As a condition to exercising the
- rights and licenses granted hereunder, each Recipient hereby
- assumes sole responsibility to secure any other intellectual
- property rights needed, if any. For example, if a third party
- patent license is required to allow Recipient to Distribute the
- Program, it is Recipient's responsibility to acquire that license
- before distributing the Program.
-
- d) Each Contributor represents that to its knowledge it has
- sufficient copyright rights in its Contribution, if any, to grant
- the copyright license set forth in this Agreement.
-
- e) Notwithstanding the terms of any Secondary License, no
- Contributor makes additional grants to any Recipient (other than
- those set forth in this Agreement) as a result of such Recipient's
- receipt of the Program under the terms of a Secondary License
- (if permitted under the terms of Section 3).
-
-3. REQUIREMENTS
-
-3.1 If a Contributor Distributes the Program in any form, then:
-
- a) the Program must also be made available as Source Code, in
- accordance with section 3.2, and the Contributor must accompany
- the Program with a statement that the Source Code for the Program
- is available under this Agreement, and informs Recipients how to
- obtain it in a reasonable manner on or through a medium customarily
- used for software exchange; and
-
- b) the Contributor may Distribute the Program under a license
- different than this Agreement, provided that such license:
- i) effectively disclaims on behalf of all other Contributors all
- warranties and conditions, express and implied, including
- warranties or conditions of title and non-infringement, and
- implied warranties or conditions of merchantability and fitness
- for a particular purpose;
-
- ii) effectively excludes on behalf of all other Contributors all
- liability for damages, including direct, indirect, special,
- incidental and consequential damages, such as lost profits;
-
- iii) does not attempt to limit or alter the recipients' rights
- in the Source Code under section 3.2; and
-
- iv) requires any subsequent distribution of the Program by any
- party to be under a license that satisfies the requirements
- of this section 3.
-
-3.2 When the Program is Distributed as Source Code:
-
- a) it must be made available under this Agreement, or if the
- Program (i) is combined with other material in a separate file or
- files made available under a Secondary License, and (ii) the initial
- Contributor attached to the Source Code the notice described in
- Exhibit A of this Agreement, then the Program may be made available
- under the terms of such Secondary Licenses, and
-
- b) a copy of this Agreement must be included with each copy of
- the Program.
-
-3.3 Contributors may not remove or alter any copyright, patent,
-trademark, attribution notices, disclaimers of warranty, or limitations
-of liability ("notices") contained within the Program from any copy of
-the Program which they Distribute, provided that Contributors may add
-their own appropriate notices.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program,
-the Contributor who includes the Program in a commercial product
-offering should do so in a manner which does not create potential
-liability for other Contributors. Therefore, if a Contributor includes
-the Program in a commercial product offering, such Contributor
-("Commercial Contributor") hereby agrees to defend and indemnify every
-other Contributor ("Indemnified Contributor") against any losses,
-damages and costs (collectively "Losses") arising from claims, lawsuits
-and other legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the Program
-in a commercial product offering. The obligations in this section do not
-apply to any claims or Losses relating to any actual or alleged
-intellectual property infringement. In order to qualify, an Indemnified
-Contributor must: a) promptly notify the Commercial Contributor in
-writing of such claim, and b) allow the Commercial Contributor to control,
-and cooperate with the Commercial Contributor in, the defense and any
-related settlement negotiations. The Indemnified Contributor may
-participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those performance
-claims and warranties, and if a court requires any other Contributor to
-pay any damages as a result, the Commercial Contributor must pay
-those damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
-PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
-BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
-IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
-TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
-PURPOSE. Each Recipient is solely responsible for determining the
-appropriateness of using and distributing the Program and assumes all
-risks associated with its exercise of rights under this Agreement,
-including but not limited to the risks and costs of program errors,
-compliance with applicable laws, damage to or loss of data, programs
-or equipment, and unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
-PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
-SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
-PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
-EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-7. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity
-(including a cross-claim or counterclaim in a lawsuit) alleging that the
-Program itself (excluding combinations of the Program with other software
-or hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and
-may only be modified in the following manner. The Agreement Steward
-reserves the right to publish new versions (including revisions) of
-this Agreement from time to time. No one other than the Agreement
-Steward has the right to modify this Agreement. The Eclipse Foundation
-is the initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-Distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is published,
-Contributor may elect to Distribute the Program (including its
-Contributions) under the new version.
-
-Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
-receives no rights or licenses to the intellectual property of any
-Contributor under this Agreement, whether expressly, by implication,
-estoppel or otherwise. All rights in the Program not expressly granted
-under this Agreement are reserved. Nothing in this Agreement is intended
-to be enforceable by any entity that is not a Contributor or Recipient.
-No third-party beneficiary rights are created under this Agreement.
-
-Exhibit A - Form of Secondary Licenses Notice
-
-"This Source Code may also be made available under the following
-Secondary Licenses when the conditions for such availability set forth
-in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
-version(s), and exceptions or additional permissions here}."
-
- Simply including a copy of this Agreement, including this Exhibit A
- is not sufficient to license the Source Code under Secondary Licenses.
-
- If it is not possible or desirable to put the notice in a particular
- file, then You may include the notice in a location (such as a LICENSE
- file in a relevant directory) where a recipient would be likely to
- look for such a notice.
-
- You may add additional accurate notices of copyright ownership.
\ No newline at end of file
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/README.rst b/README.rst
new file mode 100644
index 000000000..118241cd9
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,80 @@
+Javet
+=====
+
+Javet is Java + V8 (JAVa + V + EighT). It is yet another way of embedding V8 in Java. It was inspired by J2V8. I'll try to keep up with latest V8 in a slow pace. If you like my work, please **Star** this project. And, you may visit http://caoccao.blogspot.com/.
+
+Latest version is **0.7.0**.
+
+Major Features
+==============
+
+* It supports both Windows and Linux with V8 v8.9.255.
+* It exposes the majority of V8 API in JVM.
+* It allows injecting JS functions into V8.
+* It supports ``BigInt <-> Long``, ``Date <-> ZonedDateTime``.
+* It supports Javet engine pool like DB connection pool with a huge performance improvement.
+
+Quick Start
+===========
+
+Maven
+-----
+
+.. code-block:: xml
+
+
+ com.caoccao.javet
+ javet
+ 0.7.0
+
+
+Gradle Kotlin
+-------------
+
+.. code-block:: kotlin
+
+ dependencies {
+ implementation("com.caoccao.javet:javet:0.7.0")
+ }
+
+Gradle Groovy
+-------------
+
+.. code-block:: groovy
+
+ compile group: 'com.caoccao.javet', name: 'javet', version: '0.7.0'
+
+Hello Javet
+===========
+
+.. code-block:: java
+
+ try (V8Runtime v8Runtime = V8Host.getInstance().createV8Runtime()) {
+ v8Runtime.lock();
+ System.out.println(v8Runtime.getExecutor("'Hello Javet'").executeString());
+ }
+
+Documents
+=========
+
+* `Build `_
+* `Development `_
+* `Tutorial `_
+* `FAQ `_
+* `TODO List `_
+
+Motivation
+==========
+
+I used to take a try of J2V8 and find it's quite compelling. However, J2V8 is slowly dying, with serious memory leak issues, V8 version issue, etc.
+
+Sometimes starting from scratch implies lower cost than upgrading an existing solution. I think it might be true here in this project. I've learned quite a lot by manually fixing the Windows and Linux build system of J2V8.
+
+Also, I had got many ideas on how the API will look like. At the end of 2020, I thought I would be able to write a new one from scratch and leave J2V8 behind. Indeed, I made it few months later.
+
+Please refer to `History with J2V8 `_ for detail.
+
+License
+=======
+
+Javet follows `APACHE LICENSE, VERSION 2.0 `_.
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 000000000..07b320aae
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.
+ *
+ */
+
+plugins {
+ java
+ `java-library`
+}
+
+repositories {
+ mavenCentral()
+ jcenter()
+}
+
+group = "com.caoccao.javet"
+version = "0.7.0"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
+ runtimeOnly(fileTree("libs"))
+}
+
+afterEvaluate {
+ tasks.withType(JavaCompile::class) {
+ options.compilerArgs.add("-Xlint:unchecked")
+ options.compilerArgs.add("-Xlint:deprecation")
+ }
+}
+
+task("buildJNIHeaders") {
+ mkdir("$buildDir/generated/tmp/jni")
+ project.exec {
+ workingDir("$projectDir")
+ commandLine(
+ "javac",
+ "-h",
+ "cpp/jni",
+ "-d",
+ "$buildDir/generated/tmp/jni",
+ "src/main/java/com/caoccao/javet/interop/V8Native.java"
+ )
+ }
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
new file mode 100644
index 000000000..46c81563b
--- /dev/null
+++ b/cpp/CMakeLists.txt
@@ -0,0 +1,48 @@
+cmake_minimum_required(VERSION 3.10)
+
+if(!$ENV{JAVA_HOME})
+ message(FATAL_ERROR "JAVA_HOME is not found. Please make sure you have JDK 8 or 11 installed properly.")
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "limited configs" FORCE)
+
+# CMP0091 must be set before first project().
+# @see: https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html
+if (POLICY CMP0091)
+ cmake_policy(SET CMP0091 NEW)
+endif()
+
+project(Javet)
+aux_source_directory("jni" sourceFiles)
+add_library(v8_monolith STATIC IMPORTED)
+add_library(Javet SHARED ${sourceFiles} "jni/javet.rc")
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+set(includeDirs
+ $ENV{JAVA_HOME}/include
+ ${V8_DIR}/include
+ ${V8_DIR}/include/libplatform)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ 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$<$:Debug>")
+ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
+ set_target_properties(v8_monolith PROPERTIES IMPORTED_LOCATION ${V8_DIR}/out.gn/x64.release/obj/v8_monolith.lib)
+ set_target_properties(Javet PROPERTIES OUTPUT_NAME "libjavet-windows-x86_64.v.${JAVET_VERSION}")
+ target_link_libraries(Javet v8_monolith DbgHelp Winmm)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ list(APPEND includeDirs $ENV{JAVA_HOME}/include/linux)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64 ")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64 ")
+ set_target_properties(v8_monolith PROPERTIES IMPORTED_LOCATION ${V8_DIR}/out.gn/x64.release/obj/libv8_monolith.a)
+ set_target_properties(Javet PROPERTIES OUTPUT_NAME "javet-linux-x86_64.v.${JAVET_VERSION}")
+ target_link_libraries(Javet v8_monolith debug "-lrt" optimized "-lrt" "${libgcc}")
+else()
+ message(FATAL_ERROR "OS that is not either Windows or Linux hasn't been supported yet.")
+endif()
+
+include_directories(${includeDirs})
diff --git a/cpp/build.cmd b/cpp/build.cmd
new file mode 100644
index 000000000..29e78cc21
--- /dev/null
+++ b/cpp/build.cmd
@@ -0,0 +1,17 @@
+@echo off
+REM Usage sample: build -DV8_DIR=C:\v8
+SET JAVET_VERSION=0.7.0
+rd /s/q build
+mkdir build
+cd build
+mkdir ..\..\src\main\resources
+cmake ..\ -G "Visual Studio 16 2019" -A x64 -DJAVET_VERSION=%JAVET_VERSION% %* ^
+ && cmake --build . -- /p:CharacterSet=Unicode /p:Configuration=Release /p:Platform=x64
+IF %ERRORLEVEL% EQU 0 (
+del /q ..\..\src\main\resources\*.dll
+copy /y Release\*.dll ..\..\src\main\resources
+echo Build Completed
+) ELSE (
+echo Build Failed
+)
+cd ..\
diff --git a/cpp/build.sh b/cpp/build.sh
new file mode 100755
index 000000000..56d3fb458
--- /dev/null
+++ b/cpp/build.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Usage sample: build -DV8_DIR=~/v8
+JAVET_VERSION=0.7.0
+rm -rf build
+mkdir build
+cd build
+mkdir -p ../../src/main/resources
+cmake ../ -DJAVET_VERSION=${JAVET_VERSION} "$@" \
+ && make -j4 \
+ && execstack -c libjavet-linux-x86_64.v.${JAVET_VERSION}.so \
+ && strip --strip-unneeded -R .note -R .comment libjavet-linux-x86_64.v.${JAVET_VERSION}.so
+if [ $? -eq 0 ]; then
+ rm -f ../../src/main/resources/*.so
+ cp -f *.so ../../src/main/resources
+ echo Build Completed
+else
+ echo Build Failed
+fi
+cd ../
+
diff --git a/cpp/jni/com_caoccao_javet_interop_V8Native.cpp b/cpp/jni/com_caoccao_javet_interop_V8Native.cpp
new file mode 100644
index 000000000..cd5291d0f
--- /dev/null
+++ b/cpp/jni/com_caoccao_javet_interop_V8Native.cpp
@@ -0,0 +1,715 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "com_caoccao_javet_interop_V8Native.h"
+#include "javet_callbacks.h"
+#include "javet_constants.h"
+#include "javet_converter.h"
+#include "javet_enums.h"
+#include "javet_exceptions.h"
+#include "javet_globals.h"
+#include "javet_v8_runtime.h"
+
+ /*
+ * Development Guide:
+ * 1. Namespace is not recommended in this project.
+ * 2. Methods are expected to be sorted alphabatically except JNI_OnLoad.
+ */
+
+#define IS_JAVA_INTEGER(jniEnv, obj) jniEnv->IsInstanceOf(obj, Javet::Main::jclassV8ValueInteger)
+#define IS_JAVA_STRING(jniEnv, obj) jniEnv->IsInstanceOf(obj, Javet::Main::jclassV8ValueString)
+#define TO_JAVA_INTEGER(jniEnv, obj) jniEnv->CallIntMethod(obj, Javet::Main::jmethodIDV8ValueIntegerToPrimitive)
+#define TO_JAVA_STRING(jniEnv, obj) (jstring)jniEnv->CallObjectMethod(obj, Javet::Main::jmethodIDV8ValueStringToPrimitive)
+#define IS_V8_ARRAY(type) (type == Javet::Enums::V8ValueReferenceType::Array)
+#define IS_V8_ARGUMENTS(type) (type == Javet::Enums::V8ValueReferenceType::Arguments)
+#define IS_V8_FUNCTION(type) (type == Javet::Enums::V8ValueReferenceType::Function)
+#define IS_V8_MAP(type) (type == Javet::Enums::V8ValueReferenceType::Map)
+#define IS_V8_OBJECT(type) (type == Javet::Enums::V8ValueReferenceType::Object)
+#define IS_V8_SET(type) (type == Javet::Enums::V8ValueReferenceType::Set)
+
+#define FETCH_JNI_ENV \
+ JNIEnv* jniEnv; \
+ Javet::GlobalJavaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_8); \
+ Javet::GlobalJavaVM->AttachCurrentThread((void**)&jniEnv, nullptr); \
+
+#define RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle) \
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle); \
+ v8::Isolate::Scope v8IsolateScope(v8Runtime->v8Isolate); \
+ v8::HandleScope v8HandleScope(v8Runtime->v8Isolate); \
+ auto v8Context = v8::Local::New(v8Runtime->v8Isolate, v8Runtime->v8Context); \
+ v8::Context::Scope v8ContextScope(v8Context); \
+
+#define RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle) \
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle); \
+ auto v8PersistentObjectPointer = reinterpret_cast*>(v8ValueHandle); \
+ v8::Isolate::Scope v8IsolateScope(v8Runtime->v8Isolate); \
+ v8::HandleScope v8HandleScope(v8Runtime->v8Isolate); \
+ auto v8Context = v8::Local::New(v8Runtime->v8Isolate, v8Runtime->v8Context); \
+ v8::Context::Scope v8ContextScope(v8Context); \
+ auto v8LocalObject = v8PersistentObjectPointer->Get(v8Runtime->v8Isolate);
+
+#define SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8Value) \
+ try { \
+ return Javet::Converter::ToExternalV8Value(jniEnv, v8Context, v8Value); \
+ } \
+ catch (const std::exception& e) { \
+ Javet::Exceptions::ThrowJavetConverterException(jniEnv, e.what()); \
+ }
+
+namespace Javet {
+ namespace Main {
+ static jclass jclassV8ValueInteger;
+ static jmethodID jmethodIDV8ValueIntegerToPrimitive;
+
+ static jclass jclassV8ValueString;
+ static jmethodID jmethodIDV8ValueStringToPrimitive;
+
+ /*
+ These Java classes and methods need to be initialized within this file
+ because the memory address probed changes in another file,
+ or runtime memory corruption will take place.
+ */
+ void Initialize(JNIEnv* jniEnv) {
+ jclassV8ValueInteger = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueInteger"));
+ jmethodIDV8ValueIntegerToPrimitive = jniEnv->GetMethodID(jclassV8ValueInteger, "toPrimitive", "()I");
+
+ jclassV8ValueString = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueString"));
+ jmethodIDV8ValueStringToPrimitive = jniEnv->GetMethodID(jclassV8ValueString, "toPrimitive", "()Ljava/lang/String;");
+ }
+
+ /*
+ This callback function has to stay within the same file
+ so that the memory address doesn't get messed up.
+ */
+ void FunctionCallback(const v8::FunctionCallbackInfo& args) {
+ FETCH_JNI_ENV;
+ auto v8LocalContextHandle = args.Data().As();
+ auto umContext = reinterpret_cast(v8LocalContextHandle->Int64Value());
+ Javet::Callback::V8CallbackContextReference v8CallbackContextReference(jniEnv, umContext);
+ v8CallbackContextReference.Invoke(args);
+ }
+
+ void GlobalAccessorGetterCallback(
+ v8::Local propertyName,
+ const v8::PropertyCallbackInfo& args) {
+ args.GetReturnValue().Set(args.GetIsolate()->GetCurrentContext()->Global());
+ }
+
+ void CloseWeakObjectReference(const v8::WeakCallbackInfo& data) {
+ FETCH_JNI_ENV;
+ auto v8ValueReference = data.GetParameter();
+ v8ValueReference->Close(jniEnv);
+ delete v8ValueReference;
+ }
+ }
+}
+
+JNIEXPORT jint JNICALL JNI_OnLoad
+(JavaVM* javeVM, void*) {
+ JNIEnv* jniEnv;
+ if (javeVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_8) != JNI_OK) {
+ return ERROR_JNI_ON_LOAD;
+ }
+ if (jniEnv == nullptr) {
+ return ERROR_JNI_ON_LOAD;
+ }
+ Javet::GlobalJavaVM = javeVM;
+ v8::V8::InitializeICU();
+ Javet::GlobalV8Platform = v8::platform::NewDefaultPlatform();
+ v8::V8::InitializePlatform(Javet::GlobalV8Platform.get());
+ v8::V8::Initialize();
+ Javet::Callback::Initialize(jniEnv);
+ Javet::Converter::Initialize(jniEnv);
+ Javet::Exceptions::Initialize(jniEnv);
+ Javet::Main::Initialize(jniEnv);
+ return JNI_VERSION_1_8;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_add
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject value) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (IS_V8_SET(v8ValueType)) {
+ auto v8ValueValue = Javet::Converter::ToV8Value(jniEnv, v8Context, value);
+ auto unusedSet = v8LocalObject.As()->Add(v8Context, v8ValueValue);
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_call
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject mReceiver, jboolean mReturnResult, jobjectArray mValues) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsFunction()) {
+ v8::TryCatch v8TryCatch(v8Runtime->v8Isolate);
+ v8::MaybeLocal maybeLocalValueResult;
+ auto umReceiver = Javet::Converter::ToV8Value(jniEnv, v8Context, mReceiver);
+ uint32_t valueCount = mValues == nullptr ? 0 : jniEnv->GetArrayLength(mValues);
+ if (valueCount > 0) {
+ auto umValuesPointer = Javet::Converter::ToV8Values(jniEnv, v8Context, mValues);
+ maybeLocalValueResult = v8LocalObject.As()->Call(v8Context, umReceiver, valueCount, umValuesPointer.get());
+ }
+ else {
+ maybeLocalValueResult = v8LocalObject.As()->Call(v8Context, umReceiver, 0, nullptr);
+ }
+ if (v8TryCatch.HasCaught()) {
+ Javet::Exceptions::ThrowJavetExecutionException(jniEnv, v8Context, v8TryCatch);
+ }
+ else if (mReturnResult) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, maybeLocalValueResult.ToLocalChecked());
+ }
+ }
+ return nullptr;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_clearWeak
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject() && !v8PersistentObjectPointer->IsEmpty() && v8PersistentObjectPointer->IsWeak()) {
+ auto v8ValueReference = v8PersistentObjectPointer->ClearWeak();
+ v8ValueReference->Clear(jniEnv);
+ delete v8ValueReference;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_cloneV8Value
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ auto clonedV8LocalObject = v8::Local::New(v8Context->GetIsolate(), v8LocalObject);
+ return Javet::Converter::ToExternalV8Value(jniEnv, v8Context, clonedV8LocalObject);
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_closeV8Runtime
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle) {
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle);
+ if (v8Runtime->v8Locker != nullptr) {
+ Javet::Exceptions::ThrowJavetV8RuntimeLockConflictException(jniEnv, "Cannot close V8 runtime because the native lock is not released");
+ }
+ else {
+ v8Runtime->v8Context.Reset();
+ v8Runtime->v8GlobalObject.Reset();
+ // Isolate must be the last one to be disposed.
+ if (v8Runtime->v8Isolate != nullptr) {
+ v8Runtime->v8Isolate->Dispose();
+ v8Runtime->v8Isolate = nullptr;
+ }
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_compileOnly
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jstring mScript,
+ jstring mResourceName, jint mResourceLineOffset, jint mResourceColumnOffset, jint mScriptId, jboolean mIsWASM, jboolean mIsModule) {
+ RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle);
+ v8::TryCatch v8TryCatch(v8Runtime->v8Isolate);
+ auto umScript = Javet::Converter::ToV8String(jniEnv, v8Context, mScript);
+ v8::ScriptOrigin* scriptOriginPointer = Javet::Converter::ToV8ScriptOringinPointer(
+ jniEnv, v8Context, mResourceName, mResourceLineOffset, mResourceColumnOffset, mScriptId, mIsWASM, mIsModule);
+ auto maybeLocalCompiledScript = v8::Script::Compile(v8Context, umScript, scriptOriginPointer);
+ if (scriptOriginPointer != nullptr) {
+ delete scriptOriginPointer;
+ }
+ if (v8TryCatch.HasCaught()) {
+ Javet::Exceptions::ThrowJavetCompilationException(jniEnv, v8Context, v8TryCatch);
+ }
+}
+
+/*
+Creating multiple isolates allows running JavaScript code in multiple threads, truly parallel.
+*/
+JNIEXPORT jlong JNICALL Java_com_caoccao_javet_interop_V8Native_createV8Runtime
+(JNIEnv* jniEnv, jclass callerClass, jstring mGlobalName) {
+ auto v8Runtime = new Javet::V8Runtime();
+ v8Runtime->mException = nullptr;
+ jlong v8RuntimeHandle = reinterpret_cast(v8Runtime);
+ Java_com_caoccao_javet_interop_V8Native_resetV8Isolate(jniEnv, callerClass, v8RuntimeHandle, mGlobalName);
+ return v8RuntimeHandle;
+}
+
+/*
+It only supports Object, Array, Function, Map, Set for now.
+Error, Promise, RegExp, Proxy, Symbol, etc. are not supported.
+*/
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_createV8Value
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jint v8ValueType, jobject mContext) {
+ RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle);
+ v8::Local v8ValueValue;
+ if (IS_V8_OBJECT(v8ValueType)) {
+ v8ValueValue = v8::Object::New(v8Context->GetIsolate());
+ }
+ else if (IS_V8_ARRAY(v8ValueType)) {
+ v8ValueValue = v8::Array::New(v8Context->GetIsolate());
+ }
+ else if (IS_V8_FUNCTION(v8ValueType)) {
+ jobject umContext = jniEnv->NewGlobalRef(mContext);
+ Javet::Callback::V8CallbackContextReference v8CallbackContextReference(jniEnv, umContext);
+ v8CallbackContextReference.SetHandle();
+ auto v8LocalContextHandle = v8::BigInt::New(v8Context->GetIsolate(), reinterpret_cast(umContext));
+ v8ValueValue = v8::Function::New(v8Context, Javet::Main::FunctionCallback, v8LocalContextHandle).ToLocalChecked();
+ }
+ else if (IS_V8_MAP(v8ValueType)) {
+ v8ValueValue = v8::Map::New(v8Context->GetIsolate());
+ }
+ else if (IS_V8_SET(v8ValueType)) {
+ v8ValueValue = v8::Set::New(v8Context->GetIsolate());
+ }
+ if (!v8ValueValue.IsEmpty()) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8ValueValue);
+ }
+ return nullptr;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_delete
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, key);
+ if (IS_V8_ARRAY(v8ValueType)) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject.As()->Delete(v8Context, integerKey).FromMaybe(false);
+ }
+ else {
+ return v8LocalObject.As()->Delete(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ }
+ else if (IS_V8_MAP(v8ValueType)) {
+ return v8LocalObject.As()->Delete(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ else if (IS_V8_SET(v8ValueType)) {
+ return v8LocalObject.As()->Delete(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ else if (v8LocalObject->IsObject()) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject->Delete(v8Context, integerKey).FromMaybe(false);
+ }
+ else {
+ return v8LocalObject->Delete(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ }
+ return false;
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_execute
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jstring mScript, jboolean mReturnResult,
+ jstring mResourceName, jint mResourceLineOffset, jint mResourceColumnOffset, jint mScriptId, jboolean mIsWASM, jboolean mIsModule) {
+ RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle);
+ v8::TryCatch v8TryCatch(v8Runtime->v8Isolate);
+ auto umScript = Javet::Converter::ToV8String(jniEnv, v8Context, mScript);
+ v8::ScriptOrigin* scriptOriginPointer = Javet::Converter::ToV8ScriptOringinPointer(
+ jniEnv, v8Context, mResourceName, mResourceLineOffset, mResourceColumnOffset, mScriptId, mIsWASM, mIsModule);
+ auto maybeLocalCompiledScript = v8::Script::Compile(v8Context, umScript, scriptOriginPointer);
+ if (scriptOriginPointer != nullptr) {
+ delete scriptOriginPointer;
+ }
+ if (v8TryCatch.HasCaught()) {
+ Javet::Exceptions::ThrowJavetCompilationException(jniEnv, v8Context, v8TryCatch);
+ }
+ else if (!maybeLocalCompiledScript.IsEmpty()) {
+ v8::Local compliedScript = maybeLocalCompiledScript.ToLocalChecked();
+ v8::MaybeLocal maybeLocalValueResult = compliedScript->Run(v8Context);
+ if (v8TryCatch.HasCaught()) {
+ Javet::Exceptions::ThrowJavetExecutionException(jniEnv, v8Context, v8TryCatch);
+ }
+ else if (mReturnResult) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, maybeLocalValueResult.ToLocalChecked());
+ }
+ }
+ return nullptr;
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_get
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, key);
+ v8::Local v8ValueValue;
+ if (IS_V8_ARRAY(v8ValueType) || IS_V8_ARGUMENTS(v8ValueType)) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ if (integerKey >= 0) {
+ v8ValueValue = v8LocalObject.As()->Get(v8Context, integerKey).ToLocalChecked();
+ }
+ }
+ else if (!v8ValueKey.IsEmpty()) {
+ v8ValueValue = v8LocalObject.As()->Get(v8Context, v8ValueKey).ToLocalChecked();
+ }
+ }
+ else if (!v8ValueKey.IsEmpty()) {
+ if (IS_V8_MAP(v8ValueType)) {
+ v8ValueValue = v8LocalObject.As()->Get(v8Context, v8ValueKey).ToLocalChecked();
+ }
+ else if (IS_V8_SET(v8ValueType)) {
+ v8ValueValue = v8LocalObject.As()->Get(v8Context, v8ValueKey).ToLocalChecked();
+ }
+ else if (v8LocalObject->IsObject()) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ v8ValueValue = v8LocalObject->Get(v8Context, integerKey).ToLocalChecked();
+ }
+ else {
+ v8ValueValue = v8LocalObject->Get(v8Context, v8ValueKey).ToLocalChecked();
+ }
+ }
+ }
+ if (!v8ValueValue.IsEmpty()) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8ValueValue);
+ }
+ return Javet::Converter::ToExternalV8ValueUndefined(jniEnv);
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getGlobalObject
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle) {
+ RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle);
+ return Javet::Converter::ToExternalV8ValueGlobalObject(jniEnv, v8Runtime->v8GlobalObject);
+}
+
+JNIEXPORT jint JNICALL Java_com_caoccao_javet_interop_V8Native_getLength
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (IS_V8_ARRAY(v8ValueType)) {
+ return v8LocalObject.As()->Length();
+ }
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_caoccao_javet_interop_V8Native_getSize
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (IS_V8_MAP(v8ValueType)) {
+ return (jint)v8LocalObject.As()->Size();
+ }
+ if (IS_V8_SET(v8ValueType)) {
+ return (jint)v8LocalObject.As()->Size();
+ }
+ return 0;
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getOwnPropertyNames
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8LocalObject->GetOwnPropertyNames(v8Context).ToLocalChecked());
+ return Javet::Converter::ToExternalV8ValueUndefined(jniEnv);
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getPropertyNames
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8LocalObject->GetPropertyNames(v8Context).ToLocalChecked());
+ return Javet::Converter::ToExternalV8ValueUndefined(jniEnv);
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getProperty
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject()) {
+ v8::Local v8ValueValue;
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ v8ValueValue = v8LocalObject->Get(v8Context, integerKey).ToLocalChecked();
+ }
+ else {
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, key);
+ if (!v8ValueKey.IsEmpty()) {
+ v8ValueValue = v8LocalObject->Get(v8Context, v8ValueKey).ToLocalChecked();
+ }
+ }
+ if (!v8ValueValue.IsEmpty()) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, v8ValueValue);
+ }
+ }
+ return Javet::Converter::ToExternalV8ValueUndefined(jniEnv);
+}
+
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_getVersion
+(JNIEnv* jniEnv, jclass callerClass) {
+ const char* utfString = v8::V8::GetVersion();
+ return jniEnv->NewStringUTF(utfString);
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_has
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject value) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, value);
+ if (!v8ValueKey.IsEmpty()) {
+ if (IS_V8_MAP(v8ValueType)) {
+ return v8LocalObject.As()->Has(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ else if (IS_V8_SET(v8ValueType)) {
+ return v8LocalObject.As()->Has(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ else if (v8LocalObject->IsObject()) {
+ if (IS_JAVA_INTEGER(jniEnv, value)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, value);
+ return v8LocalObject->Has(v8Context, integerKey).FromMaybe(false);
+ }
+ else {
+ return v8LocalObject->Has(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ }
+ }
+ return false;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_hasOwnProperty
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject()) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject->HasOwnProperty(v8Context, integerKey).FromMaybe(false);
+ }
+ else if (IS_JAVA_STRING(jniEnv, key)) {
+ jstring stringKey = TO_JAVA_STRING(jniEnv, key);
+ auto v8ValueKey = Javet::Converter::ToV8String(jniEnv, v8Context, stringKey);
+ return v8LocalObject->HasOwnProperty(v8Context, v8ValueKey).FromMaybe(false);
+ }
+ }
+ return false;
+}
+
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_invoke
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jstring mFunctionName, jboolean mReturnResult, jobjectArray mValues) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject()) {
+ auto v8Function = v8LocalObject->Get(v8Context, Javet::Converter::ToV8String(jniEnv, v8Context, mFunctionName)).ToLocalChecked();
+ if (v8Function->IsFunction()) {
+ v8::TryCatch v8TryCatch(v8Runtime->v8Isolate);
+ v8::MaybeLocal maybeLocalValueResult;
+ uint32_t valueCount = mValues == nullptr ? 0 : jniEnv->GetArrayLength(mValues);
+ if (valueCount > 0) {
+ auto umValuesPointer = Javet::Converter::ToV8Values(jniEnv, v8Context, mValues);
+ maybeLocalValueResult = v8Function.As()->Call(v8Context, v8LocalObject, valueCount, umValuesPointer.get());
+ }
+ else {
+ maybeLocalValueResult = v8Function.As()->Call(v8Context, v8LocalObject, 0, nullptr);
+ }
+ if (v8TryCatch.HasCaught()) {
+ Javet::Exceptions::ThrowJavetExecutionException(jniEnv, v8Context, v8TryCatch);
+ }
+ else if (mReturnResult) {
+ SAFE_CONVERT_AND_RETURN_JAVE_V8_VALUE(jniEnv, v8Context, maybeLocalValueResult.ToLocalChecked());
+ }
+ }
+ }
+ return nullptr;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_isWeak
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject() && !v8PersistentObjectPointer->IsEmpty()) {
+ return (jboolean)v8PersistentObjectPointer->IsWeak();
+ }
+ return false;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_lockV8Runtime
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle) {
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle);
+ if (v8Runtime->v8Locker != nullptr) {
+ Javet::Exceptions::ThrowJavetV8RuntimeLockConflictException(jniEnv, "Cannot acquire V8 native lock because it has not been released yet");
+ }
+ else {
+ v8Runtime->v8Locker = new v8::Locker(v8Runtime->v8Isolate);
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_removeJNIGlobalRef
+(JNIEnv* jniEnv, jclass callerClass, jlong handle) {
+ jniEnv->DeleteGlobalRef((jobject)handle);
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_removeReferenceHandle
+(JNIEnv* jniEnv, jclass callerClass, jlong referenceHandle) {
+ auto v8PersistentObjectPointer = reinterpret_cast*>(referenceHandle);
+ v8PersistentObjectPointer->Reset();
+ delete v8PersistentObjectPointer;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_requestGarbageCollectionForTesting
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jboolean fullGC) {
+ RUNTIME_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle);
+ v8Runtime->v8Isolate->RequestGarbageCollectionForTesting(((bool)fullGC)
+ ? v8::Isolate::GarbageCollectionType::kFullGarbageCollection
+ : v8::Isolate::GarbageCollectionType::kMinorGarbageCollection);
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_resetV8Context
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jstring mGlobalName) {
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle);
+ v8::Locker v8Locker(v8Runtime->v8Isolate);
+ v8::Isolate::Scope v8IsolateScope(v8Runtime->v8Isolate);
+ // Create a stack-allocated handle scope.
+ v8::HandleScope v8HandleScope(v8Runtime->v8Isolate);
+ auto v8IsolateHandle = v8::ObjectTemplate::New(v8Runtime->v8Isolate);
+ auto v8Context = v8::Context::New(v8Runtime->v8Isolate, nullptr, v8IsolateHandle);
+ // Redirects global calls to a given global name. E.g. parseInt() -> window.parseInt().
+ if (mGlobalName != nullptr) {
+ auto umGlobalName = Javet::Converter::ToV8String(jniEnv, v8Context, mGlobalName);
+ v8IsolateHandle->SetAccessor(umGlobalName, Javet::Main::GlobalAccessorGetterCallback);
+ }
+ v8Runtime->v8Context.Reset(v8Runtime->v8Isolate, v8Context);
+ v8Runtime->v8GlobalObject.Reset(
+ v8Runtime->v8Isolate,
+ v8Context->Global()->GetPrototype()->ToObject(v8Context).ToLocalChecked());
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_resetV8Isolate
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jstring mGlobalName) {
+ Java_com_caoccao_javet_interop_V8Native_closeV8Runtime(jniEnv, callerClass, v8RuntimeHandle);
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle);
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
+ v8Runtime->v8Isolate = v8::Isolate::New(create_params);
+ v8::Locker v8Locker(v8Runtime->v8Isolate);
+ v8::Isolate::Scope v8IsolateScope(v8Runtime->v8Isolate);
+ // Create a stack-allocated handle scope.
+ v8::HandleScope v8HandleScope(v8Runtime->v8Isolate);
+ auto v8IsolateHandle = v8::ObjectTemplate::New(v8Runtime->v8Isolate);
+ auto v8Context = v8::Context::New(v8Runtime->v8Isolate, nullptr, v8IsolateHandle);
+ // Redirects global calls to a given global name. E.g. parseInt() -> window.parseInt().
+ if (mGlobalName != nullptr) {
+ auto umGlobalName = Javet::Converter::ToV8String(jniEnv, v8Context, mGlobalName);
+ v8IsolateHandle->SetAccessor(umGlobalName, Javet::Main::GlobalAccessorGetterCallback);
+ }
+ v8Runtime->v8Context.Reset(v8Runtime->v8Isolate, v8Context);
+ v8Runtime->v8GlobalObject.Reset(
+ v8Runtime->v8Isolate,
+ v8Context->Global()->GetPrototype()->ToObject(v8Context).ToLocalChecked());
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_set
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key, jobject value) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, key);
+ auto v8ValueValue = Javet::Converter::ToV8Value(jniEnv, v8Context, value);
+ if (IS_V8_ARRAY(v8ValueType)) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject.As()->Set(v8Context, integerKey, v8ValueValue).FromMaybe(false);
+ }
+ else if (!v8ValueKey.IsEmpty()) {
+ return v8LocalObject.As()->Set(v8Context, v8ValueKey, v8ValueValue).FromMaybe(false);
+ }
+ }
+ else if (!v8ValueKey.IsEmpty()) {
+ if (IS_V8_MAP(v8ValueType)) {
+ auto unusedSet = v8LocalObject.As()->Set(v8Context, v8ValueKey, v8ValueValue);
+ return true;
+ }
+ else if (v8LocalObject->IsObject()) {
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject->Set(v8Context, integerKey, v8ValueValue).FromMaybe(false);
+ }
+ else {
+ return v8LocalObject->Set(v8Context, v8ValueKey, v8ValueValue).FromMaybe(false);
+ }
+ }
+ }
+ return false;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_setFlags
+(JNIEnv* jniEnv, jclass, jstring flags) {
+ if (flags) {
+ char const* str = jniEnv->GetStringUTFChars(flags, nullptr);
+ v8::V8::SetFlagsFromString(str, jniEnv->GetStringUTFLength(flags));
+ jniEnv->ReleaseStringUTFChars(flags, str);
+ v8::V8::Initialize();
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_setProperty
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject key, jobject value) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject()) {
+ auto v8ValueValue = Javet::Converter::ToV8Value(jniEnv, v8Context, value);
+ if (IS_JAVA_INTEGER(jniEnv, key)) {
+ jint integerKey = TO_JAVA_INTEGER(jniEnv, key);
+ return v8LocalObject->Set(v8Context, integerKey, v8ValueValue).FromMaybe(false);
+ }
+ else {
+ auto v8ValueKey = Javet::Converter::ToV8Value(jniEnv, v8Context, key);
+ if (!v8ValueKey.IsEmpty()) {
+ return v8LocalObject->Set(v8Context, v8ValueKey, v8ValueValue).FromMaybe(false);
+ }
+ }
+ }
+ return false;
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_setWeak
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobject objectReference) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ if (v8LocalObject->IsObject() && !v8PersistentObjectPointer->IsEmpty() && !v8PersistentObjectPointer->IsWeak()) {
+ auto v8ValueReference = new Javet::Callback::V8ValueReference;
+ v8ValueReference->v8Isolate = v8Context->GetIsolate();
+ v8ValueReference->objectReference = jniEnv->NewGlobalRef(objectReference);
+ v8ValueReference->v8PersistentObjectPointer = v8PersistentObjectPointer;
+ v8PersistentObjectPointer->SetWeak(v8ValueReference, Javet::Main::CloseWeakObjectReference, v8::WeakCallbackType::kParameter);
+ }
+}
+
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_toProtoString
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ v8::Local v8String;
+ if (v8LocalObject->IsObject()) {
+ v8String = v8LocalObject->ObjectProtoToString(v8Context).ToLocalChecked();
+ }
+ v8::String::Value stringValue(v8Context->GetIsolate(), v8String);
+ return jniEnv->NewString(*stringValue, stringValue.length());
+}
+
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_toString
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType) {
+ RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle);
+ v8::Local v8String;
+ if (IS_V8_ARRAY(v8ValueType)) {
+ v8String = v8LocalObject.As()->ToString(v8Context).ToLocalChecked();
+ }
+ else if (IS_V8_MAP(v8ValueType)) {
+ v8String = v8LocalObject.As()->ToString(v8Context).ToLocalChecked();
+ }
+ else if (IS_V8_SET(v8ValueType)) {
+ v8String = v8LocalObject.As()->ToString(v8Context).ToLocalChecked();
+ }
+ else if (v8LocalObject->IsObject()) {
+ v8String = v8LocalObject->ToString(v8Context).ToLocalChecked();
+ }
+ v8::String::Value stringValue(v8Context->GetIsolate(), v8String);
+ return jniEnv->NewString(*stringValue, stringValue.length());
+}
+
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_unlockV8Runtime
+(JNIEnv* jniEnv, jclass callerClass, jlong v8RuntimeHandle) {
+ auto v8Runtime = reinterpret_cast(v8RuntimeHandle);
+ if (v8Runtime->v8Locker == nullptr) {
+ Javet::Exceptions::ThrowJavetV8RuntimeLockConflictException(jniEnv, "Cannot release V8 native lock because it has not been acquired yet");
+ }
+ else {
+ delete v8Runtime->v8Locker;
+ v8Runtime->v8Locker = nullptr;
+ }
+}
+
diff --git a/cpp/jni/com_caoccao_javet_interop_V8Native.h b/cpp/jni/com_caoccao_javet_interop_V8Native.h
new file mode 100644
index 000000000..8a79de8e4
--- /dev/null
+++ b/cpp/jni/com_caoccao_javet_interop_V8Native.h
@@ -0,0 +1,293 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_caoccao_javet_interop_V8Native */
+
+#ifndef _Included_com_caoccao_javet_interop_V8Native
+#define _Included_com_caoccao_javet_interop_V8Native
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: add
+ * Signature: (JJILjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_add
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: call
+ * Signature: (JJILjava/lang/Object;Z[Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_call
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject, jboolean, jobjectArray);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: clearWeak
+ * Signature: (JJI)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_clearWeak
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: cloneV8Value
+ * Signature: (JJI)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_cloneV8Value
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: closeV8Runtime
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_closeV8Runtime
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: compileOnly
+ * Signature: (JLjava/lang/String;Ljava/lang/String;IIIZZ)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_compileOnly
+ (JNIEnv *, jclass, jlong, jstring, jstring, jint, jint, jint, jboolean, jboolean);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: createV8Runtime
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_caoccao_javet_interop_V8Native_createV8Runtime
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: createV8Value
+ * Signature: (JILjava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_createV8Value
+ (JNIEnv *, jclass, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: delete
+ * Signature: (JJILjava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_delete
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: execute
+ * Signature: (JLjava/lang/String;ZLjava/lang/String;IIIZZ)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_execute
+ (JNIEnv *, jclass, jlong, jstring, jboolean, jstring, jint, jint, jint, jboolean, jboolean);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: get
+ * Signature: (JJILjava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_get
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getGlobalObject
+ * Signature: (J)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getGlobalObject
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getLength
+ * Signature: (JJI)I
+ */
+JNIEXPORT jint JNICALL Java_com_caoccao_javet_interop_V8Native_getLength
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getSize
+ * Signature: (JJI)I
+ */
+JNIEXPORT jint JNICALL Java_com_caoccao_javet_interop_V8Native_getSize
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getOwnPropertyNames
+ * Signature: (JJI)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getOwnPropertyNames
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getPropertyNames
+ * Signature: (JJI)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getPropertyNames
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getProperty
+ * Signature: (JJILjava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_getProperty
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: getVersion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_getVersion
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: has
+ * Signature: (JJILjava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_has
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: hasOwnProperty
+ * Signature: (JJILjava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_hasOwnProperty
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: invoke
+ * Signature: (JJILjava/lang/String;Z[Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_invoke
+ (JNIEnv *, jclass, jlong, jlong, jint, jstring, jboolean, jobjectArray);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: isWeak
+ * Signature: (JJI)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_isWeak
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: lockV8Runtime
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_lockV8Runtime
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: removeJNIGlobalRef
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_removeJNIGlobalRef
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: removeReferenceHandle
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_removeReferenceHandle
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: requestGarbageCollectionForTesting
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_requestGarbageCollectionForTesting
+ (JNIEnv *, jclass, jlong, jboolean);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: resetV8Context
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_resetV8Context
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: resetV8Isolate
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_resetV8Isolate
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: set
+ * Signature: (JJILjava/lang/Object;Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_set
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: setFlags
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_setFlags
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: setProperty
+ * Signature: (JJILjava/lang/Object;Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_setProperty
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: setWeak
+ * Signature: (JJILjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_setWeak
+ (JNIEnv *, jclass, jlong, jlong, jint, jobject);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: toProtoString
+ * Signature: (JJI)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_toProtoString
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: toString
+ * Signature: (JJI)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_caoccao_javet_interop_V8Native_toString
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_caoccao_javet_interop_V8Native
+ * Method: unlockV8Runtime
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_caoccao_javet_interop_V8Native_unlockV8Runtime
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/cpp/jni/javet.rc b/cpp/jni/javet.rc
new file mode 100644
index 000000000..527095e95
--- /dev/null
+++ b/cpp/jni/javet.rc
@@ -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,7,0,0
+ PRODUCTVERSION 0,7,0,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.7.0.0"
+ VALUE "InternalName", "javet-windows-x86_64.v.0.7.0.dll"
+ VALUE "LegalCopyright", "Copyright (C) 2021"
+ VALUE "OriginalFilename", "javet-windows-x86_64.v.0.7.0.dll"
+ VALUE "ProductName", "Javet Windows"
+ VALUE "ProductVersion", "0.7.0.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
+
diff --git a/cpp/jni/javet_callbacks.cpp b/cpp/jni/javet_callbacks.cpp
new file mode 100644
index 000000000..3f57ae72a
--- /dev/null
+++ b/cpp/jni/javet_callbacks.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#include "javet_callbacks.h"
+#include "javet_constants.h"
+#include "javet_converter.h"
+#include "javet_globals.h"
+
+namespace Javet {
+ namespace Callback {
+ void V8ValueReference::Clear(JNIEnv* jniEnv) {
+ if (v8PersistentObjectPointer != nullptr) {
+ jniEnv->DeleteGlobalRef(objectReference);
+ }
+ }
+
+ void V8ValueReference::Close(JNIEnv* jniEnv) {
+ if (v8PersistentObjectPointer != nullptr) {
+ v8PersistentObjectPointer->Reset();
+ v8PersistentObjectPointer = nullptr;
+ jniEnv->CallVoidMethod(reinterpret_cast(objectReference), jmethodIDIV8ValueReferenceClose, true);
+ jniEnv->DeleteGlobalRef(objectReference);
+ }
+ }
+
+ V8CallbackContextReference::V8CallbackContextReference(JNIEnv* jniEnv, jobject callbackContext) {
+ this->jniEnv = jniEnv;
+ this->callbackContext = callbackContext;
+ }
+
+ jobject V8CallbackContextReference::GetCallbackOwnerFunction() {
+ return jniEnv->CallObjectMethod(callbackContext, jmethodIDV8CallbackContextGetCallbackOwnerFunction);
+ }
+
+ void V8CallbackContextReference::Invoke(const v8::FunctionCallbackInfo& args) {
+ v8::Isolate* v8Isolate = args.GetIsolate();
+ v8::Isolate::Scope v8IsolateScope(v8Isolate);
+ v8::HandleScope v8HandleScope(v8Isolate);
+ auto v8Context = v8Isolate->GetCurrentContext();
+ jobject callbackOwnerFunction = GetCallbackOwnerFunction();
+ jboolean isReturnResult = IsReturnResult();
+ jboolean isThisObjectRequired = IsThisObjectRequired();
+ jobject externalArgs = Javet::Converter::ToExternalV8ValueArray(jniEnv, v8Context, args);
+ jobject thisObject = isThisObjectRequired ? Javet::Converter::ToExternalV8Value(jniEnv, v8Context, args.This()) : nullptr;
+ jobject mResult = jniEnv->CallObjectMethod(callbackOwnerFunction, jmethodIDIV8ValueFunctionReceiveCallback, thisObject, externalArgs);
+ if (jniEnv->ExceptionCheck()) {
+ jthrowable externalException = jniEnv->ExceptionOccurred();
+ jstring externalErrorMessage = (jstring)jniEnv->CallObjectMethod(externalException, jmethodIDThrowableGetMessage);
+ jniEnv->ExceptionClear();
+ v8::Local v8ErrorMessage;
+ if (externalErrorMessage == nullptr) {
+ v8ErrorMessage = v8::String::NewFromUtf8(v8Isolate, "Uncaught JavaError: unknown").ToLocalChecked();
+ }
+ else {
+ v8ErrorMessage = Javet::Converter::ToV8String(jniEnv, v8Context, externalErrorMessage);
+ jniEnv->DeleteLocalRef(externalErrorMessage);
+ }
+ v8Isolate->ThrowException(v8::Exception::Error(v8ErrorMessage));
+ jniEnv->DeleteLocalRef(externalException);
+ }
+ else if (isReturnResult) {
+ if (mResult == nullptr) {
+ args.GetReturnValue().SetUndefined();
+ }
+ else {
+ args.GetReturnValue().Set(Javet::Converter::ToV8Value(jniEnv, v8Context, mResult));
+ }
+ }
+ if (thisObject != nullptr) {
+ jniEnv->DeleteLocalRef(thisObject);
+ }
+ if (externalArgs != nullptr) {
+ jniEnv->DeleteLocalRef(externalArgs);
+ }
+ if (mResult != nullptr) {
+ jniEnv->CallStaticVoidMethod(jclassJavetResourceUtils, jmethodIDJavetResourceUtilsSafeClose, mResult);
+ jniEnv->DeleteLocalRef(mResult);
+ }
+ }
+
+ jboolean V8CallbackContextReference::IsReturnResult() {
+ return jniEnv->CallBooleanMethod(callbackContext, jmethodIDV8CallbackContextIsReturnResult);
+ }
+
+ jboolean V8CallbackContextReference::IsThisObjectRequired() {
+ return jniEnv->CallBooleanMethod(callbackContext, jmethodIDV8CallbackContextIsThisObjectRequired);
+ }
+
+ void V8CallbackContextReference::SetHandle() {
+ jniEnv->CallVoidMethod(callbackContext, jmethodIDV8CallbackContextSetHandle, reinterpret_cast(callbackContext));
+ }
+
+ void Initialize(JNIEnv* jniEnv) {
+ jclassIV8ValueFunction = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass(
+ "com/caoccao/javet/values/reference/IV8ValueFunction"));
+ jmethodIDIV8ValueFunctionReceiveCallback = jniEnv->GetMethodID(
+ jclassIV8ValueFunction,
+ "receiveCallback",
+ "(Lcom/caoccao/javet/values/V8Value;Lcom/caoccao/javet/values/reference/V8ValueArray;)Lcom/caoccao/javet/values/V8Value;");
+
+ jclassIV8ValueReference = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass(
+ "com/caoccao/javet/values/reference/IV8ValueReference"));
+ jmethodIDIV8ValueReferenceClose = jniEnv->GetMethodID(jclassIV8ValueReference, "close", "(Z)V");
+
+ jclassJavetResourceUtils = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/utils/JavetResourceUtils"));
+ jmethodIDJavetResourceUtilsSafeClose = jniEnv->GetStaticMethodID(jclassJavetResourceUtils, "safeClose", "(Ljava/lang/Object;)V");
+
+ jclassThrowable = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("java/lang/Throwable"));
+ jmethodIDThrowableGetMessage = jniEnv->GetMethodID(jclassThrowable, "getMessage", "()Ljava/lang/String;");
+
+ jclassV8CallbackContext = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/utils/V8CallbackContext"));
+ jmethodIDV8CallbackContextGetCallbackOwnerFunction = jniEnv->GetMethodID(
+ jclassV8CallbackContext,
+ "getCallbackOwnerFunction",
+ "()Lcom/caoccao/javet/values/reference/IV8ValueFunction;");
+ jmethodIDV8CallbackContextIsReturnResult = jniEnv->GetMethodID(jclassV8CallbackContext, "isReturnResult", "()Z");
+ jmethodIDV8CallbackContextIsThisObjectRequired = jniEnv->GetMethodID(jclassV8CallbackContext, "isThisObjectRequired", "()Z");
+ jmethodIDV8CallbackContextSetHandle = jniEnv->GetMethodID(jclassV8CallbackContext, "setHandle", "(J)V");
+ }
+ }
+}
+
diff --git a/cpp/jni/javet_callbacks.h b/cpp/jni/javet_callbacks.h
new file mode 100644
index 000000000..fddcee692
--- /dev/null
+++ b/cpp/jni/javet_callbacks.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include "javet_v8_runtime.h"
+
+namespace Javet {
+ namespace Callback {
+
+ class V8ValueReference {
+ public:
+ v8::Isolate* v8Isolate;
+ jobject objectReference;
+ v8::Persistent* v8PersistentObjectPointer;
+ void Clear(JNIEnv* jniEnv);
+ void Close(JNIEnv* jniEnv);
+ };
+
+ class V8CallbackContextReference {
+ public:
+ jobject callbackContext;
+ JNIEnv* jniEnv;
+ V8CallbackContextReference(JNIEnv* jniEnv, jobject callbackContext);
+ jobject GetCallbackOwnerFunction();
+ void Invoke(const v8::FunctionCallbackInfo& args);
+ jboolean IsReturnResult();
+ jboolean IsThisObjectRequired();
+ void SetHandle();
+ };
+
+ static jclass jclassIV8ValueFunction;
+ static jmethodID jmethodIDIV8ValueFunctionReceiveCallback;
+
+ static jclass jclassIV8ValueReference;
+ static jmethodID jmethodIDIV8ValueReferenceClose;
+
+ static jclass jclassJavetResourceUtils;
+ static jmethodID jmethodIDJavetResourceUtilsSafeClose;
+
+ static jclass jclassThrowable;
+ static jmethodID jmethodIDThrowableGetMessage;
+
+ static jclass jclassV8CallbackContext;
+ static jmethodID jmethodIDV8CallbackContextGetCallbackOwnerFunction;
+ static jmethodID jmethodIDV8CallbackContextIsReturnResult;
+ static jmethodID jmethodIDV8CallbackContextIsThisObjectRequired;
+ static jmethodID jmethodIDV8CallbackContextSetHandle;
+
+ void Initialize(JNIEnv* jniEnv);
+ }
+}
diff --git a/cpp/jni/javet_constants.h b/cpp/jni/javet_constants.h
new file mode 100644
index 000000000..a8d962a4c
--- /dev/null
+++ b/cpp/jni/javet_constants.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+#define ERROR_JNI_ON_LOAD -1;
diff --git a/cpp/jni/javet_converter.cpp b/cpp/jni/javet_converter.cpp
new file mode 100644
index 000000000..0f2795551
--- /dev/null
+++ b/cpp/jni/javet_converter.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#include "javet_converter.h"
+
+ // Primitive
+#define IS_JAVA_BOOLEAN(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueBoolean)
+#define IS_JAVA_DOUBLE(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueDouble)
+#define IS_JAVA_INTEGER(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueInteger)
+#define IS_JAVA_LONG(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueLong)
+#define IS_JAVA_NULL(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueNull)
+#define IS_JAVA_STRING(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueString)
+#define IS_JAVA_UNDEFINED(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueUndefined)
+#define IS_JAVA_ZONED_DATE_TIME(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueZonedDateTime)
+
+// Reference
+#define IS_JAVA_ARGUMENTS(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueArguments)
+#define IS_JAVA_ARRAY(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueArray)
+#define IS_JAVA_FUNCTION(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueFunction)
+#define IS_JAVA_ERROR(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueError)
+#define IS_JAVA_GLOBAL_OBJECT(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueGlobalObject)
+#define IS_JAVA_MAP(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueMap)
+#define IS_JAVA_OBJECT(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueObject)
+#define IS_JAVA_PROMISE(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValuePromise)
+#define IS_JAVA_PROXY(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueProxy)
+#define IS_JAVA_REFERENCE(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueReference)
+#define IS_JAVA_REG_EXP(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueRegExp)
+#define IS_JAVA_SET(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueSet)
+#define IS_JAVA_SYMBOL(jniEnv, obj) jniEnv->IsInstanceOf(obj, jclassV8ValueSymbol)
+
+namespace Javet {
+ namespace Converter {
+ void Initialize(JNIEnv* jniEnv) {
+ /*
+ @see https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
+ @see https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
+ */
+
+ // Primitive
+
+ jclassV8ValueBoolean = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueBoolean"));
+ jmethodIDV8ValueBooleanConstructor = jniEnv->GetMethodID(jclassV8ValueBoolean, "", "(Z)V");
+ jmethodIDV8ValueBooleanToPrimitive = jniEnv->GetMethodID(jclassV8ValueBoolean, "toPrimitive", "()Z");
+
+ jclassV8ValueDouble = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueDouble"));
+ jmethodIDV8ValueDoubleConstructor = jniEnv->GetMethodID(jclassV8ValueDouble, "", "(D)V");
+ jmethodIDV8ValueDoubleToPrimitive = jniEnv->GetMethodID(jclassV8ValueDouble, "toPrimitive", "()D");
+
+ jclassV8ValueInteger = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueInteger"));
+ jmethodIDV8ValueIntegerConstructor = jniEnv->GetMethodID(jclassV8ValueInteger, "", "(I)V");
+ jmethodIDV8ValueIntegerToPrimitive = jniEnv->GetMethodID(jclassV8ValueInteger, "toPrimitive", "()I");
+
+ jclassV8ValueLong = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueLong"));
+ jmethodIDV8ValueLongConstructorFromLong = jniEnv->GetMethodID(jclassV8ValueLong, "", "(J)V");
+ jmethodIDV8ValueLongConstructorFromString = jniEnv->GetMethodID(jclassV8ValueLong, "", "(Ljava/lang/String;)V");
+ jmethodIDV8ValueLongToPrimitive = jniEnv->GetMethodID(jclassV8ValueLong, "toPrimitive", "()J");
+
+ jclassV8ValueNull = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueNull"));
+ jmethodIDV8ValueNullConstructor = jniEnv->GetMethodID(jclassV8ValueNull, "", "()V");
+
+ jclassV8ValueString = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueString"));
+ jmethodIDV8ValueStringConstructor = jniEnv->GetMethodID(jclassV8ValueString, "", "(Ljava/lang/String;)V");
+ jmethodIDV8ValueStringToPrimitive = jniEnv->GetMethodID(jclassV8ValueString, "toPrimitive", "()Ljava/lang/String;");
+
+ jclassV8ValueUndefined = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueUndefined"));
+ jmethodIDV8ValueUndefinedConstructor = jniEnv->GetMethodID(jclassV8ValueUndefined, "", "()V");
+
+ jclassV8ValueUnknown = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueUnknown"));
+ jmethodIDV8ValueUnknownConstructor = jniEnv->GetMethodID(jclassV8ValueUnknown, "", "(Ljava/lang/String;)V");
+
+ jclassV8ValueZonedDateTime = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/primitive/V8ValueZonedDateTime"));
+ jmethodIDV8ValueZonedDateTimeConstructor = jniEnv->GetMethodID(jclassV8ValueZonedDateTime, "", "(J)V");
+ jmethodIDV8ValueZonedDateTimeToPrimitive = jniEnv->GetMethodID(jclassV8ValueZonedDateTime, "toPrimitive", "()J");
+
+ // Reference
+
+ jclassV8ValueArguments = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueArguments"));
+ jmethodIDV8ValueArgumentsConstructor = jniEnv->GetMethodID(jclassV8ValueArguments, "", "(J)V");
+ jmethodIDV8ValueArgumentsGetHandle = jniEnv->GetMethodID(jclassV8ValueArguments, "getHandle", "()J");
+
+ jclassV8ValueArray = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueArray"));
+ jmethodIDV8ValueArrayConstructor = jniEnv->GetMethodID(jclassV8ValueArray, "", "(J)V");
+ jmethodIDV8ValueArrayGetHandle = jniEnv->GetMethodID(jclassV8ValueArray, "getHandle", "()J");
+
+ jclassV8ValueFunction = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueFunction"));
+ jmethodIDV8ValueFunctionConstructor = jniEnv->GetMethodID(jclassV8ValueFunction, "", "(J)V");
+ jmethodIDV8ValueFunctionGetHandle = jniEnv->GetMethodID(jclassV8ValueFunction, "getHandle", "()J");
+
+ jclassV8ValueError = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueError"));
+ jmethodIDV8ValueErrorConstructor = jniEnv->GetMethodID(jclassV8ValueError, "", "(J)V");
+ jmethodIDV8ValueErrorGetHandle = jniEnv->GetMethodID(jclassV8ValueError, "getHandle", "()J");
+
+ jclassV8ValueGlobalObject = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueGlobalObject"));
+ jmethodIDV8ValueGlobalObjectConstructor = jniEnv->GetMethodID(jclassV8ValueGlobalObject, "", "(J)V");
+ jmethodIDV8ValueGlobalObjectGetHandle = jniEnv->GetMethodID(jclassV8ValueGlobalObject, "getHandle", "()J");
+
+ jclassV8ValueMap = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueMap"));
+ jmethodIDV8ValueMapConstructor = jniEnv->GetMethodID(jclassV8ValueMap, "", "(J)V");
+ jmethodIDV8ValueMapGetHandle = jniEnv->GetMethodID(jclassV8ValueMap, "getHandle", "()J");
+
+ jclassV8ValueObject = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueObject"));
+ jmethodIDV8ValueObjectConstructor = jniEnv->GetMethodID(jclassV8ValueObject, "", "(J)V");
+ jmethodIDV8ValueObjectGetHandle = jniEnv->GetMethodID(jclassV8ValueObject, "getHandle", "()J");
+
+ jclassV8ValuePromise = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValuePromise"));
+ jmethodIDV8ValuePromiseConstructor = jniEnv->GetMethodID(jclassV8ValuePromise, "", "(J)V");
+ jmethodIDV8ValuePromiseGetHandle = jniEnv->GetMethodID(jclassV8ValuePromise, "getHandle", "()J");
+
+ jclassV8ValueProxy = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueProxy"));
+ jmethodIDV8ValueProxyConstructor = jniEnv->GetMethodID(jclassV8ValueProxy, "", "(J)V");
+ jmethodIDV8ValueProxyGetHandle = jniEnv->GetMethodID(jclassV8ValueProxy, "getHandle", "()J");
+
+ jclassV8ValueReference = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueReference"));
+
+ jclassV8ValueRegExp = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueRegExp"));
+ jmethodIDV8ValueRegExpConstructor = jniEnv->GetMethodID(jclassV8ValueRegExp, "", "(J)V");
+ jmethodIDV8ValueRegExpGetHandle = jniEnv->GetMethodID(jclassV8ValueRegExp, "getHandle", "()J");
+
+ jclassV8ValueSet = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueSet"));
+ jmethodIDV8ValueSetConstructor = jniEnv->GetMethodID(jclassV8ValueSet, "", "(J)V");
+ jmethodIDV8ValueSetGetHandle = jniEnv->GetMethodID(jclassV8ValueSet, "getHandle", "()J");
+
+ jclassV8ValueSymbol = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/values/reference/V8ValueSymbol"));
+ jmethodIDV8ValueSymbolConstructor = jniEnv->GetMethodID(jclassV8ValueSymbol, "", "(J)V");
+ jmethodIDV8ValueSymbolGetHandle = jniEnv->GetMethodID(jclassV8ValueSymbol, "getHandle", "()J");
+ }
+
+ jobject ToExternalV8ValueArray(JNIEnv* jniEnv, v8::Local& v8Context, const v8::FunctionCallbackInfo& args) {
+ int argLength = args.Length();
+ if (argLength > 0) {
+ auto v8Array = v8::Array::New(v8Context->GetIsolate(), argLength);
+ for (int i = 0; i < argLength; ++i) {
+ auto maybeResult = v8Array->Set(v8Context, i, args[i]);
+ maybeResult.Check();
+ }
+ return ToExternalV8Value(jniEnv, v8Context, v8Array);
+ }
+ return nullptr;
+ }
+
+ jobject ToExternalV8Value(JNIEnv* jniEnv, v8::Local& v8Context, v8::Local v8Value) {
+ if (v8Value->IsUndefined()) {
+ return ToExternalV8ValueUndefined(jniEnv);
+ }
+ if (v8Value->IsNull()) {
+ return ToExternalV8ValueNull(jniEnv);
+ }
+ // Reference types
+ // Note: Reference types must be checked before primitive types are checked.
+ if (v8Value->IsArray()) {
+ return jniEnv->NewObject(jclassV8ValueArray, jmethodIDV8ValueArrayConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsTypedArray()) {
+ // TODO
+ if (v8Value->IsBigInt64Array()) {
+ }
+ if (v8Value->IsBigUint64Array()) {
+ }
+ if (v8Value->IsFloat32Array()) {
+ }
+ if (v8Value->IsFloat64Array()) {
+ }
+ if (v8Value->IsInt16Array()) {
+ }
+ if (v8Value->IsInt32Array()) {
+ }
+ if (v8Value->IsInt8Array()) {
+ }
+ if (v8Value->IsUint16Array()) {
+ }
+ if (v8Value->IsUint32Array()) {
+ }
+ if (v8Value->IsUint8Array()) {
+ }
+ if (v8Value->IsUint8ClampedArray()) {
+ }
+ }
+ if (v8Value->IsArrayBuffer()) {
+ // TODO
+ }
+ if (v8Value->IsArrayBufferView()) {
+ // TODO
+ }
+ if (v8Value->IsMap()) {
+ return jniEnv->NewObject(jclassV8ValueMap, jmethodIDV8ValueMapConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsMapIterator()) {
+ // It defaults to V8ValueObject.
+ }
+ if (v8Value->IsSet()) {
+ return jniEnv->NewObject(jclassV8ValueSet, jmethodIDV8ValueSetConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsSetIterator()) {
+ // It defaults to V8ValueObject.
+ }
+ if (v8Value->IsWeakMap()) {
+ // TODO
+ }
+ if (v8Value->IsWeakSet()) {
+ // TODO
+ }
+ if (v8Value->IsArgumentsObject()) {
+ return jniEnv->NewObject(jclassV8ValueArguments, jmethodIDV8ValueArgumentsConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsPromise()) {
+ return jniEnv->NewObject(jclassV8ValuePromise, jmethodIDV8ValuePromiseConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsRegExp()) {
+ return jniEnv->NewObject(jclassV8ValueRegExp, jmethodIDV8ValueRegExpConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsGeneratorObject()) {
+ // TODO
+ }
+ if (v8Value->IsAsyncFunction()) {
+ // TODO
+ }
+ if (v8Value->IsGeneratorFunction()) {
+ // TODO
+ }
+ if (v8Value->IsProxy()) {
+ // Proxy is also a function. So, it needs to be tested before IsFunction().
+ return jniEnv->NewObject(jclassV8ValueProxy, jmethodIDV8ValueProxyConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsFunction()) {
+ return jniEnv->NewObject(jclassV8ValueFunction, jmethodIDV8ValueFunctionConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsNativeError()) {
+ return jniEnv->NewObject(jclassV8ValueError, jmethodIDV8ValueErrorConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ if (v8Value->IsSymbol() || v8Value->IsSymbolObject()) {
+ return jniEnv->NewObject(jclassV8ValueSymbol, jmethodIDV8ValueSymbolConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ // Primitive types
+ if (v8Value->IsBoolean() || v8Value->IsBooleanObject()) {
+ return jniEnv->NewObject(jclassV8ValueBoolean, jmethodIDV8ValueBooleanConstructor, v8Value->IsTrue());
+ }
+ if (v8Value->IsInt32()) {
+ return jniEnv->NewObject(jclassV8ValueInteger, jmethodIDV8ValueIntegerConstructor, v8Value->Int32Value(v8Context).FromMaybe(0));
+ }
+ if (v8Value->IsBigInt() || v8Value->IsBigIntObject()) {
+#ifdef JAVET_CONVERTER_BIGINT_STANDARD
+ // This is the standard way of getting int64.
+ return jniEnv->NewObject(jclassV8ValueLong, jmethodIDV8ValueLongConstructorFromLong,
+ v8Value->ToBigInt(v8Context).ToLocalChecked()->Int64Value());
+#else
+ // There is another way of getting int64. This branch is disabled by default.
+ v8::String::Value stringValue(v8Context->GetIsolate(), v8Value);
+ jstring mStringValue = jniEnv->NewString(*stringValue, stringValue.length());
+ jobject mV8Value = jniEnv->NewObject(jclassV8ValueLong, jmethodIDV8ValueLongConstructorFromString, mStringValue);
+ jniEnv->DeleteLocalRef(mStringValue);
+ return mV8Value;
+#endif // JAVET_CONVERTER_BIGINT_STANDARD
+ }
+ if (v8Value->IsDate()) {
+ auto v8Date = v8Value->ToObject(v8Context).ToLocalChecked().As();
+ return jniEnv->NewObject(jclassV8ValueZonedDateTime, jmethodIDV8ValueZonedDateTimeConstructor, static_cast(v8Date->ValueOf()));
+ }
+ if (v8Value->IsNumber() || v8Value->IsNumberObject()) {
+ return jniEnv->NewObject(jclassV8ValueDouble, jmethodIDV8ValueDoubleConstructor, v8Value->NumberValue(v8Context).FromMaybe(0));
+ }
+ if (v8Value->IsString() || v8Value->IsStringObject()) {
+ return ToExternalV8ValuePrimitive(jniEnv, jclassV8ValueString, jmethodIDV8ValueStringConstructor, v8Context, v8Value);
+ }
+ if (v8Value->IsName()) {
+ // It defaults to V8ValueObject.
+ }
+ // Object needs to be the last one.
+ if (v8Value->IsObject()) {
+ return jniEnv->NewObject(jclassV8ValueObject, jmethodIDV8ValueObjectConstructor, ToV8PersistentObjectReference(v8Context, v8Value));
+ }
+ // Something is wrong. It defaults to toString().
+ return ToExternalV8ValuePrimitive(jniEnv, jclassV8ValueUnknown, jmethodIDV8ValueUnknownConstructor, v8Context, v8Value);
+ }
+
+ inline jobject ToExternalV8ValueNull(JNIEnv* jniEnv) {
+ return jniEnv->NewObject(jclassV8ValueNull, jmethodIDV8ValueNullConstructor);
+ }
+
+ jobject ToExternalV8ValueGlobalObject(JNIEnv* jniEnv, v8::Persistent& v8PersistentObject) {
+ return jniEnv->NewObject(jclassV8ValueGlobalObject, jmethodIDV8ValueGlobalObjectConstructor, reinterpret_cast(&v8PersistentObject));
+ }
+
+ inline jobject ToExternalV8ValuePrimitive(
+ JNIEnv* jniEnv, jclass jclassV8ValuePrimitive, jmethodID jmethodIDV8ValuePrimitiveConstructor,
+ v8::Local& v8Context, v8::Local v8Value) {
+ v8::String::Value stringValue(v8Context->GetIsolate(), v8Value->ToString(v8Context).ToLocalChecked());
+ jstring mStringValue = jniEnv->NewString(*stringValue, stringValue.length());
+ jobject mV8ValuePrimitive = jniEnv->NewObject(jclassV8ValuePrimitive, jmethodIDV8ValuePrimitiveConstructor, mStringValue);
+ jniEnv->DeleteLocalRef(mStringValue);
+ return mV8ValuePrimitive;
+ }
+
+ jobject ToExternalV8ValueUndefined(JNIEnv* jniEnv) {
+ return jniEnv->NewObject(jclassV8ValueUndefined, jmethodIDV8ValueUndefinedConstructor);
+ }
+
+ inline v8::Local ToV8Boolean(v8::Local& v8Context, jboolean& managedBoolean) {
+ return v8::Boolean::New(v8Context->GetIsolate(), managedBoolean);
+ }
+
+ inline v8::Local ToV8Date(v8::Local& v8Context, jlong& managedLong) {
+ return v8::Date::New(v8Context, (double)managedLong).ToLocalChecked();
+ }
+
+ inline v8::Local ToV8Double(v8::Local& v8Context, jdouble& managedDouble) {
+ return v8::Number::New(v8Context->GetIsolate(), managedDouble);
+ }
+
+ inline v8::Local ToV8Integer(v8::Local& v8Context, jint& managedInteger) {
+ return v8::Integer::New(v8Context->GetIsolate(), managedInteger);
+ }
+
+ inline v8::Local ToV8Long(v8::Local& v8Context, jlong& managedLong) {
+ return v8::BigInt::New(v8Context->GetIsolate(), managedLong);
+ }
+
+ inline v8::Local ToV8Null(v8::Local& v8Context) {
+ return v8::Null(v8Context->GetIsolate());
+ }
+
+ inline v8::Local ToV8Undefined(v8::Local& v8Context) {
+ return v8::Undefined(v8Context->GetIsolate());
+ }
+
+ inline jlong ToV8PersistentObjectReference(v8::Local& v8Context, v8::Local v8Value) {
+ v8::Persistent* v8PersistentObjectPointer = new v8::Persistent(
+ v8Context->GetIsolate(),
+ v8Value->ToObject(v8Context).ToLocalChecked());
+ return reinterpret_cast(v8PersistentObjectPointer);
+ }
+
+ v8::ScriptOrigin* ToV8ScriptOringinPointer(JNIEnv* jniEnv, v8::Local& v8Context,
+ jstring& mResourceName, jint& mResourceLineOffset, jint& mResourceColumnOffset, jint& mScriptId, jboolean& mIsWASM, jboolean& mIsModule) {
+ if (mResourceName == nullptr) {
+ return nullptr;
+ }
+ return new v8::ScriptOrigin(
+ ToV8String(jniEnv, v8Context, mResourceName),
+ ToV8Integer(v8Context, mResourceLineOffset),
+ ToV8Integer(v8Context, mResourceColumnOffset),
+ v8::Local(),
+ ToV8Integer(v8Context, mScriptId),
+ v8::Local(),
+ v8::Local(),
+ ToV8Boolean(v8Context, mIsWASM),
+ ToV8Boolean(v8Context, mIsModule),
+ v8::Local());
+ }
+
+ v8::Local ToV8String(JNIEnv* jniEnv, v8::Local& v8Context, jstring& managedString) {
+ const uint16_t* unmanagedString = jniEnv->GetStringChars(managedString, nullptr);
+ int length = jniEnv->GetStringLength(managedString);
+ auto twoByteString = v8::String::NewFromTwoByte(
+ v8Context->GetIsolate(), unmanagedString, v8::NewStringType::kNormal, length);
+ if (twoByteString.IsEmpty()) {
+ return v8::Local();
+ }
+ auto localV8String = twoByteString.ToLocalChecked();
+ jniEnv->ReleaseStringChars(managedString, unmanagedString);
+ return localV8String;
+ }
+
+ v8::Local ToV8Value(JNIEnv* jniEnv, v8::Local& v8Context, jobject& obj) {
+ if (obj == nullptr || IS_JAVA_NULL(jniEnv, obj)) {
+ return ToV8Null(v8Context);
+ }
+ else if (IS_JAVA_INTEGER(jniEnv, obj)) {
+ jint integerObject = jniEnv->CallIntMethod(obj, jmethodIDV8ValueIntegerToPrimitive);
+ return ToV8Integer(v8Context, integerObject);
+ }
+ else if (IS_JAVA_STRING(jniEnv, obj)) {
+ jstring stringObject = (jstring)jniEnv->CallObjectMethod(obj, jmethodIDV8ValueStringToPrimitive);
+ return ToV8String(jniEnv, v8Context, stringObject);
+ }
+ else if (IS_JAVA_BOOLEAN(jniEnv, obj)) {
+ jboolean booleanObject = jniEnv->CallBooleanMethod(obj, jmethodIDV8ValueBooleanToPrimitive);
+ return ToV8Boolean(v8Context, booleanObject);
+ }
+ else if (IS_JAVA_DOUBLE(jniEnv, obj)) {
+ jdouble doubleObject = jniEnv->CallDoubleMethod(obj, jmethodIDV8ValueDoubleToPrimitive);
+ return ToV8Double(v8Context, doubleObject);
+ }
+ else if (IS_JAVA_LONG(jniEnv, obj)) {
+ jlong longObject = jniEnv->CallLongMethod(obj, jmethodIDV8ValueLongToPrimitive);
+ return ToV8Long(v8Context, longObject);
+ }
+ else if (IS_JAVA_ZONED_DATE_TIME(jniEnv, obj)) {
+ jlong longObject = (jlong)jniEnv->CallObjectMethod(obj, jmethodIDV8ValueZonedDateTimeToPrimitive);
+ return ToV8Date(v8Context, longObject);
+ }
+ else if (IS_JAVA_REFERENCE(jniEnv, obj)) {
+ if (IS_JAVA_ARGUMENTS(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueArgumentsGetHandle)));
+ }
+ else if (IS_JAVA_ARRAY(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueArrayGetHandle)));
+ }
+ else if (IS_JAVA_ERROR(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueErrorGetHandle)));
+ }
+ else if (IS_JAVA_GLOBAL_OBJECT(jniEnv, obj)) {
+ // Global object is a tricky one.
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueGlobalObjectGetHandle)));
+ }
+ else if (IS_JAVA_MAP(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueMapGetHandle)));
+ }
+ else if (IS_JAVA_OBJECT(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueObjectGetHandle)));
+ }
+ else if (IS_JAVA_PROMISE(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValuePromiseGetHandle)));
+ }
+ else if (IS_JAVA_PROXY(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueProxyGetHandle)));
+ }
+ else if (IS_JAVA_REG_EXP(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueRegExpGetHandle)));
+ }
+ else if (IS_JAVA_SET(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueSetGetHandle)));
+ }
+ else if (IS_JAVA_SYMBOL(jniEnv, obj)) {
+ return v8::Local::New(v8Context->GetIsolate(), *reinterpret_cast*>(
+ jniEnv->CallLongMethod(obj, jmethodIDV8ValueSymbolGetHandle)));
+ }
+ }
+ return ToV8Undefined(v8Context);
+ }
+
+ std::unique_ptr[]> ToV8Values(JNIEnv* jniEnv, v8::Local& v8Context, jobjectArray& mValues) {
+ std::unique_ptr[]> umValuesPointer;
+ uint32_t valueCount = mValues == nullptr ? 0 : jniEnv->GetArrayLength(mValues);
+ if (valueCount > 0) {
+ umValuesPointer.reset(new v8::Local[valueCount]);
+ for (uint32_t i = 0; i < valueCount; ++i) {
+ jobject obj = jniEnv->GetObjectArrayElement(mValues, i);
+ umValuesPointer.get()[i] = ToV8Value(jniEnv, v8Context, obj);
+ }
+ }
+ return umValuesPointer;
+ }
+ }
+}
diff --git a/cpp/jni/javet_converter.h b/cpp/jni/javet_converter.h
new file mode 100644
index 000000000..9bbe848b9
--- /dev/null
+++ b/cpp/jni/javet_converter.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+
+#pragma once
+
+#include
+#include
+
+#define JAVET_CONVERTER_BIGINT_STANDARD
+
+namespace Javet {
+ namespace Converter {
+ // Primitive
+
+ static jclass jclassV8ValueBoolean;
+ static jmethodID jmethodIDV8ValueBooleanConstructor;
+ static jmethodID jmethodIDV8ValueBooleanToPrimitive;
+
+ static jclass jclassV8ValueDouble;
+ static jmethodID jmethodIDV8ValueDoubleConstructor;
+ static jmethodID jmethodIDV8ValueDoubleToPrimitive;
+
+ static jclass jclassV8ValueInteger;
+ static jmethodID jmethodIDV8ValueIntegerConstructor;
+ static jmethodID jmethodIDV8ValueIntegerToPrimitive;
+
+ static jclass jclassV8ValueLong;
+ static jmethodID jmethodIDV8ValueLongConstructorFromLong;
+ static jmethodID jmethodIDV8ValueLongConstructorFromString;
+ static jmethodID jmethodIDV8ValueLongToPrimitive;
+
+ static jclass jclassV8ValueNull;
+ static jmethodID jmethodIDV8ValueNullConstructor;
+
+ static jclass jclassV8ValueString;
+ static jmethodID jmethodIDV8ValueStringConstructor;
+ static jmethodID jmethodIDV8ValueStringToPrimitive;
+
+ static jclass jclassV8ValueUndefined;
+ static jmethodID jmethodIDV8ValueUndefinedConstructor;
+
+ static jclass jclassV8ValueUnknown;
+ static jmethodID jmethodIDV8ValueUnknownConstructor;
+
+ static jclass jclassV8ValueZonedDateTime;
+ static jmethodID jmethodIDV8ValueZonedDateTimeConstructor;
+ static jmethodID jmethodIDV8ValueZonedDateTimeToPrimitive;
+
+ // Reference
+
+ static jclass jclassV8ValueArguments;
+ static jmethodID jmethodIDV8ValueArgumentsConstructor;
+ static jmethodID jmethodIDV8ValueArgumentsGetHandle;
+
+ static jclass jclassV8ValueArray;
+ static jmethodID jmethodIDV8ValueArrayConstructor;
+ static jmethodID jmethodIDV8ValueArrayGetHandle;
+
+ static jclass jclassV8ValueFunction;
+ static jmethodID jmethodIDV8ValueFunctionConstructor;
+ static jmethodID jmethodIDV8ValueFunctionGetHandle;
+
+ static jclass jclassV8ValueError;
+ static jmethodID jmethodIDV8ValueErrorConstructor;
+ static jmethodID jmethodIDV8ValueErrorGetHandle;
+
+ static jclass jclassV8ValueGlobalObject;
+ static jmethodID jmethodIDV8ValueGlobalObjectConstructor;
+ static jmethodID jmethodIDV8ValueGlobalObjectGetHandle;
+
+ static jclass jclassV8ValueMap;
+ static jmethodID jmethodIDV8ValueMapConstructor;
+ static jmethodID jmethodIDV8ValueMapGetHandle;
+
+ static jclass jclassV8ValueObject;
+ static jmethodID jmethodIDV8ValueObjectConstructor;
+ static jmethodID jmethodIDV8ValueObjectGetHandle;
+
+ static jclass jclassV8ValuePromise;
+ static jmethodID jmethodIDV8ValuePromiseConstructor;
+ static jmethodID jmethodIDV8ValuePromiseGetHandle;
+
+ static jclass jclassV8ValueProxy;
+ static jmethodID jmethodIDV8ValueProxyConstructor;
+ static jmethodID jmethodIDV8ValueProxyGetHandle;
+
+ static jclass jclassV8ValueReference;
+
+ static jclass jclassV8ValueRegExp;
+ static jmethodID jmethodIDV8ValueRegExpConstructor;
+ static jmethodID jmethodIDV8ValueRegExpGetHandle;
+
+ static jclass jclassV8ValueSet;
+ static jmethodID jmethodIDV8ValueSetConstructor;
+ static jmethodID jmethodIDV8ValueSetGetHandle;
+
+ static jclass jclassV8ValueSymbol;
+ static jmethodID jmethodIDV8ValueSymbolConstructor;
+ static jmethodID jmethodIDV8ValueSymbolGetHandle;
+
+ void Initialize(JNIEnv* jniEnv);
+
+ jobject ToExternalV8Value(JNIEnv* jniEnv, v8::Local& v8Context, v8::Local v8Value);
+
+ jobject ToExternalV8ValueArray(JNIEnv* jniEnv, v8::Local& v8Context, const v8::FunctionCallbackInfo& args);
+
+ inline jobject ToExternalV8ValueNull(JNIEnv* jniEnv);
+
+ jobject ToExternalV8ValueGlobalObject(JNIEnv* jniEnv, v8::Persistent& v8PersistentObject);
+
+ inline jobject ToExternalV8ValuePrimitive(
+ JNIEnv* jniEnv, jclass jclassV8ValuePrimitive, jmethodID jmethodIDV8ValuePrimitiveConstructor,
+ v8::Local& v8Context, v8::Local v8Value);
+
+ jobject ToExternalV8ValueUndefined(JNIEnv* jniEnv);
+
+ inline v8::Local ToV8Boolean(v8::Local& v8Context, jboolean& managedBoolean);
+
+ inline v8::Local ToV8Date(v8::Local& v8Context, jlong& managedLong);
+
+ inline v8::Local ToV8Double(v8::Local& v8Context, jdouble& managedDouble);
+
+ inline v8::Local ToV8Integer(v8::Local& v8Context, jint& managedInteger);
+
+ inline v8::Local ToV8Long(v8::Local& v8Context, jlong& managedLong);
+
+ inline v8::Local ToV8Null(v8::Local& v8Context);
+
+ inline v8::Local ToV8Undefined(v8::Local& v8Context);
+
+ inline jlong ToV8PersistentObjectReference(v8::Local& v8Context, v8::Local v8Value);
+
+ v8::ScriptOrigin* ToV8ScriptOringinPointer(JNIEnv* jniEnv, v8::Local& v8Context,
+ jstring& mResourceName, jint& mResourceLineOffset, jint& mResourceColumnOffset, jint& mScriptId, jboolean& mIsWASM, jboolean& mIsModule);
+
+ v8::Local ToV8String(JNIEnv* jniEnv, v8::Local& v8Context, jstring& managedString);
+
+ v8::Local ToV8Value(JNIEnv* jniEnv, v8::Local& v8Context, jobject& obj);
+
+ std::unique_ptr[]> ToV8Values(JNIEnv* jniEnv, v8::Local& v8Context, jobjectArray& mValues);
+ }
+}
diff --git a/cpp/jni/javet_enums.h b/cpp/jni/javet_enums.h
new file mode 100644
index 000000000..001853c44
--- /dev/null
+++ b/cpp/jni/javet_enums.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+namespace Javet {
+ namespace Enums {
+ enum V8ValueReferenceType {
+ Object = 1,
+ Error = 2,
+ RegExp = 3,
+ Promise = 4,
+ Proxy = 5,
+ Symbol = 6,
+ Arguments = 7,
+ Map = 8,
+ Set = 9,
+ Array = 10,
+ Function = 11,
+ };
+ }
+}
\ No newline at end of file
diff --git a/cpp/jni/javet_exceptions.cpp b/cpp/jni/javet_exceptions.cpp
new file mode 100644
index 000000000..70b64947f
--- /dev/null
+++ b/cpp/jni/javet_exceptions.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#include "javet_converter.h"
+#include "javet_exceptions.h"
+
+namespace Javet {
+ namespace Exceptions {
+ void Initialize(JNIEnv* jniEnv) {
+ /*
+ @see https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
+ @see https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
+ */
+
+ jclassJavetCompilationException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetCompilationException"));
+ jmethodIDJavetCompilationExceptionConstructor = jniEnv->GetMethodID(jclassJavetCompilationException, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIII)V");
+ jclassJavetConverterException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetConverterException"));
+ jclassJavetExecutionException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetExecutionException"));
+ jmethodIDJavetExecutionExceptionConstructor = jniEnv->GetMethodID(jclassJavetExecutionException, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIII)V");
+ jclassJavetUnknownCompilationException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetUnknownCompilationException"));
+ jmethodIDJavetUnknownCompilationExceptionConstructor = jniEnv->GetMethodID(jclassJavetUnknownCompilationException, "", "(Ljava/lang/String;)V");
+ jclassJavetUnknownExecutionException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetUnknownExecutionException"));
+ jmethodIDJavetUnknownExecutionExceptionConstructor = jniEnv->GetMethodID(jclassJavetUnknownExecutionException, "", "(Ljava/lang/String;)V");
+ jclassJavetV8RuntimeLockConflictException = (jclass)jniEnv->NewGlobalRef(jniEnv->FindClass("com/caoccao/javet/exceptions/JavetV8RuntimeLockConflictException"));
+ }
+
+ void ThrowJavetCompilationException(JNIEnv* jniEnv, const v8::Local& v8Context, const v8::TryCatch& v8TryCatch) {
+ auto isolate = v8Context->GetIsolate();
+ v8::String::Value exceptionMessage(isolate, v8TryCatch.Exception());
+ jstring jStringExceptionMessage = jniEnv->NewString(*exceptionMessage, exceptionMessage.length());
+ auto compileErrorMessage = v8TryCatch.Message();
+ if (compileErrorMessage.IsEmpty()) {
+ jthrowable javetUnknownCompilationException = (jthrowable)jniEnv->NewObject(
+ jclassJavetUnknownCompilationException,
+ jmethodIDJavetUnknownCompilationExceptionConstructor,
+ jStringExceptionMessage);
+ jniEnv->Throw(javetUnknownCompilationException);
+ }
+ else {
+ v8::String::Utf8Value scriptResourceName(isolate, compileErrorMessage->GetScriptResourceName());
+ jstring jStringScriptResourceName = jniEnv->NewStringUTF(*scriptResourceName);
+ v8::String::Value sourceLine(isolate, compileErrorMessage->GetSourceLine(v8Context).ToLocalChecked());
+ jstring jStringSourceLine = jniEnv->NewString(*sourceLine, sourceLine.length());
+ jthrowable javetConverterException = (jthrowable)jniEnv->NewObject(
+ jclassJavetCompilationException,
+ jmethodIDJavetCompilationExceptionConstructor,
+ jStringExceptionMessage,
+ jStringScriptResourceName,
+ jStringSourceLine,
+ compileErrorMessage->GetLineNumber(v8Context).FromMaybe(0),
+ compileErrorMessage->GetStartColumn(),
+ compileErrorMessage->GetEndColumn(),
+ compileErrorMessage->GetStartPosition(),
+ compileErrorMessage->GetEndPosition() );
+ jniEnv->Throw(javetConverterException);
+ jniEnv->DeleteLocalRef(jStringSourceLine);
+ jniEnv->DeleteLocalRef(jStringScriptResourceName);
+ }
+ jniEnv->DeleteLocalRef(jStringExceptionMessage);
+ }
+
+ void ThrowJavetConverterException(JNIEnv* jniEnv, const char* message) {
+ jniEnv->ThrowNew(jclassJavetConverterException, message);
+ }
+
+ void ThrowJavetExecutionException(JNIEnv* jniEnv, const v8::Local& v8Context, const v8::TryCatch& v8TryCatch) {
+ auto isolate = v8Context->GetIsolate();
+ v8::String::Value exceptionMessage(isolate, v8TryCatch.Exception());
+ jstring jStringExceptionMessage = jniEnv->NewString(*exceptionMessage, exceptionMessage.length());
+ auto compileErrorMessage = v8TryCatch.Message();
+ if (compileErrorMessage.IsEmpty()) {
+ jthrowable javetUnknownExecutionException = (jthrowable)jniEnv->NewObject(
+ jclassJavetUnknownExecutionException,
+ jmethodIDJavetUnknownExecutionExceptionConstructor,
+ jStringExceptionMessage);
+ jniEnv->Throw(javetUnknownExecutionException);
+ }
+ else {
+ v8::String::Utf8Value scriptResourceName(isolate, compileErrorMessage->GetScriptResourceName());
+ jstring jStringScriptResourceName = jniEnv->NewStringUTF(*scriptResourceName);
+ v8::String::Value sourceLine(isolate, compileErrorMessage->GetSourceLine(v8Context).ToLocalChecked());
+ jstring jStringSourceLine = jniEnv->NewString(*sourceLine, sourceLine.length());
+ jthrowable javetConverterException = (jthrowable)jniEnv->NewObject(
+ jclassJavetExecutionException,
+ jmethodIDJavetExecutionExceptionConstructor,
+ jStringExceptionMessage,
+ jStringScriptResourceName,
+ jStringSourceLine,
+ compileErrorMessage->GetLineNumber(v8Context).FromMaybe(0),
+ compileErrorMessage->GetStartColumn(),
+ compileErrorMessage->GetEndColumn(),
+ compileErrorMessage->GetStartPosition(),
+ compileErrorMessage->GetEndPosition() );
+ jniEnv->Throw(javetConverterException);
+ jniEnv->DeleteLocalRef(jStringSourceLine);
+ jniEnv->DeleteLocalRef(jStringScriptResourceName);
+ }
+ jniEnv->DeleteLocalRef(jStringExceptionMessage);
+ }
+
+ void ThrowJavetV8RuntimeLockConflictException(JNIEnv* jniEnv, const char* message) {
+ jniEnv->ThrowNew(jclassJavetV8RuntimeLockConflictException, message);
+ }
+ }
+}
diff --git a/cpp/jni/javet_exceptions.h b/cpp/jni/javet_exceptions.h
new file mode 100644
index 000000000..f1cab06cd
--- /dev/null
+++ b/cpp/jni/javet_exceptions.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Javet {
+ namespace Exceptions {
+ static jclass jclassJavetCompilationException;
+ static jmethodID jmethodIDJavetCompilationExceptionConstructor;
+ static jclass jclassJavetConverterException;
+ static jclass jclassJavetExecutionException;
+ static jmethodID jmethodIDJavetExecutionExceptionConstructor;
+ static jclass jclassJavetUnknownCompilationException;
+ static jmethodID jmethodIDJavetUnknownCompilationExceptionConstructor;
+ static jclass jclassJavetUnknownExecutionException;
+ static jmethodID jmethodIDJavetUnknownExecutionExceptionConstructor;
+ static jclass jclassJavetV8RuntimeLockConflictException;
+
+ void Initialize(JNIEnv* jniEnv);
+
+ void ThrowJavetCompilationException(JNIEnv* jniEnv, const v8::Local& v8Context, const v8::TryCatch& v8TryCatch);
+ void ThrowJavetConverterException(JNIEnv* jniEnv, const char* message);
+ void ThrowJavetExecutionException(JNIEnv* jniEnv, const v8::Local& v8Context, const v8::TryCatch& v8TryCatch);
+ void ThrowJavetV8RuntimeLockConflictException(JNIEnv* jniEnv, const char* message);
+ }
+}
diff --git a/cpp/jni/javet_globals.h b/cpp/jni/javet_globals.h
new file mode 100644
index 000000000..8b0864ffb
--- /dev/null
+++ b/cpp/jni/javet_globals.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Javet {
+ static std::unique_ptr GlobalV8Platform = nullptr;
+ static JavaVM* GlobalJavaVM = nullptr;
+}
+
diff --git a/cpp/jni/javet_v8_runtime.h b/cpp/jni/javet_v8_runtime.h
new file mode 100644
index 000000000..e08dc5193
--- /dev/null
+++ b/cpp/jni/javet_v8_runtime.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace Javet {
+
+ class V8Runtime {
+ public:
+ v8::Isolate* v8Isolate;
+ v8::Persistent v8Context;
+ v8::Persistent v8GlobalObject;
+ v8::Locker* v8Locker;
+ jthrowable mException;
+ v8_inspector::V8Inspector* v8Inspector;
+ };
+
+}
+
diff --git a/cpp/jni/resource.h b/cpp/jni/resource.h
new file mode 100644
index 000000000..cf6e7f457
--- /dev/null
+++ b/cpp/jni/resource.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by javet.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/docs/build.rst b/docs/build.rst
new file mode 100644
index 000000000..bd3e3f92f
--- /dev/null
+++ b/docs/build.rst
@@ -0,0 +1,92 @@
+=====
+Build
+=====
+
+Build Environment
+=================
+
+Linux Environment
+-----------------
+
+* CMake 3.10+
+* Ubuntu 18.04
+* JDK 8
+
+Windows Environment
+-------------------
+
+* Latest Windows 10
+* Visual Studio 2019 Community
+* CMake 3.16+ (comes with Visual Studio)
+* Latest Windows 10 SDK with WinDbg
+* JDK 8
+
+Download Pre-built V8
+=====================
+
+I have prepared pre-built Linux and Windows version of V8 v8.9.255. Please download the headers and binary from this `drive `_ and unzip them locally.
+
+Build Javet JNI Library
+=======================
+
+Once V8 is ready, please navigate to ``./cpp``, make sure CMake is accessible and execute corresponding build script.
+
+* Linux - ``sh build.sh -DV8_DIR=/where_the_v8_directory_is``.
+* Windows - ``build.cmd -DV8_DIR=\where_the_v8_directory_is``.
+
+Note: The V8 directory needs to be absolute path.
+
+After a while, ``libjavet-linux-x86_64.v.*.*.*.so`` or ``libjavet-windows-x86_64.v.*.*.*.dll`` will be placed in folder ``src/main/resources``.
+
+Build Javet Jar
+===============
+
+Once both ``libjavet-linux-x86_64.v.*.*.*.so`` and ``libjavet-windows-x86_64.v.*.*.*.dll`` are built, please put them altogether under ``src/main/resources`` then kick off ``gradle build test``.
+
+After a while, ``javet-*.*.*.jar`` will be placed in folder ``build/libs``.
+
+Note: This jar file supports both Linux and Windows.
+
+Upload Javet to Maven Central (Optional)
+----------------------------------------
+
+Package Jar files in Maven.
+
+.. code-block:: sh
+
+ # mvn package
+ mvn clean
+ mvn release:prepare
+ mvn release:perform
+
+Jar files are built under ``./target``.
+
+Build V8 (Optional)
+===================
+
+Please follow the `official guide `_ to build V8 ``8.9.255. If you face any issues, you may contact `@sjtucaocao `_.
+
+Some Tips on Building V8
+------------------------
+
+* Linux requires Python 2.7, CMake 3.10+. Ubuntu 18.04 is the recommended Linux distribution.
+* Windows requires Windows 10, Python 2.7, Visual Studio 2019 Community, CMake (comes with Visual Studio), Windows 10 SDK with WinDbg.
+
+Also, please make sure ``args.gn`` file looks like the following.
+
+.. code-block:: ini
+
+ is_debug = false
+ target_cpu = "x64"
+ v8_monolithic = true
+ v8_use_external_startup_data = false
+ is_component_build = false
+ v8_enable_i18n_support= false
+ v8_enable_pointer_compression = false
+ v8_static_library = true
+ symbol_level = 0
+ use_custom_libcxx = false
+
+``v8_monolith`` is the build target.
+
+[`Home <../README.rst>`_]
diff --git a/docs/development.rst b/docs/development.rst
new file mode 100644
index 000000000..fb1a5970e
--- /dev/null
+++ b/docs/development.rst
@@ -0,0 +1,33 @@
+===========
+Development
+===========
+
+Development Tools
+=================
+
+JDK
+---
+
+Javet development requires JDK 8 to be installed, though Javet supports JDK 8+. JDK 6 support has been dropped because a few JDK 8 features are heavily used in Javet.
+
+IDE
+---
+
+I personally recommend IntelliJ IDEA.
+
+Gradle
+------
+
+For now, Gradle v6.7 + Kotlin DSL constructs the build system.
+
+Maven
+-----
+
+Maven v3.6.3+ is the one.
+
+NodeJS
+------
+
+NodeJS 14.5+ is required if you want to go over the tutorial because a few examples use some node modules. After installing NodeJS, please visit ``scripts/node`` directory and run ``npm install``.
+
+[`Home <../README.rst>`_]
diff --git a/README.md b/docs/faq/history_with_j2v8.rst
similarity index 58%
rename from README.md
rename to docs/faq/history_with_j2v8.rst
index 98b012131..4663e4b91 100644
--- a/README.md
+++ b/docs/faq/history_with_j2v8.rst
@@ -1,63 +1,46 @@
-# Javet
+History with J2V8
+=================
-Javet is Java + V8 (JAVa + V + EighT). It is yet another way of embedding V8 in Java. It was inspired by J2V8.
-
-## Why Javet?
-
-### J2V8 Issues
+J2V8 Issues
+===========
J2V8 is an excellent project on embedding V8 in Java. However, J2V8 community hasn't been active since 2017.
The last Windows version 4.6.0 was released on 2016 and the last Linux version 4.8.0 was released on 2017. The V8 in Windows v4.6.0 doesn't even fully support ES6.
-The latest community activities were around Android versions. The NodeJS API was dropped. The Windows build has been seriously broken for years. The Linux build is nearly broken.
+The latest community activities were around Android versions. The NodeJS API was dropped. The Windows build has been seriously broken for years. The Linux build is nearly broken. There are serious memory leak issues which are hard to be fixed under the current architecture.
Its API has stopped evolving for years. Many new features I expect just don't get any chances to be implemented. Obviously, if the build system was broken and couldn't be easily fixed, almost no one would like to contribute. That includes me. When I was trying to fix the build system for Windows and Linux, I had to admit that's so, so, so, challenging. Why is that? I think it's not merely J2V8 community's problem because in the meanwhile V8, NodeJS and ECMAScript move forward rapidly causing many unexpected challenges. Someone or some team needs to look after J2V8 from time to time. Unfortunately, reality is cruel.
-### Well, Why not Let Me Start from Scratch?
-
-Sometimes starting from scratch implies lower cost than upgrading an existing solution. I think it might be true here in this project. I've learned quite a lot by manually fixing the Windows and Linux build system.
-
-Also, I've got many ideas on how the API will look like. I think I would be able to write a new one from scratch and leave J2V8 behind.
-
-## Javet Project Status
+J2V8 Latest Version
+===================
-This is kind of a personal project, yet still on paper.
-
-### TODO List
-
-* To start from scratch so that there is no legal issues to J2V8.
-* To support Windows and Linux. Supporting MacOS calls for your help.
-* To implement unified `V8Object` covering primitive types.
-* To implement V8 runtime pool like DB connection pool. The performance test shows there is a huge gap (millions vs. hundreds) between pooled and non-pooled V8 runtime.
-* To support more types that are not supported by ECMAScript, e.g. Long, BigDecimal, etc.
-* To revive NodeJS.
-* To implement runtime debugging capability.
-
-### What Can I Use?
-
-For now, please try the latest [J2V8 v6.2.0](https://github.com/caoccao/Javet/releases/tag/0.6.2.0) unofficially released by me. I'll try to keep up with latest V8 in a slow pace. If you like my work, please **Star** this project. And, you may send messages to [@sjtucaocao](https://twitter.com/sjtucaocao).
+I managed to unofficially built the latest `J2V8 v6.2.0 `_.
* V8 is upgraded to v8.3.110.9 which was released in May, 2020.
* Windows and Linux are supported.
* NodeJS is dropped temporarily.
-I've tested the performance between `j2v8_win32_x86_64-4.6.0.jar` and `j2v8_win32_x86_64-6.2.0.jar` on a Windows machine with CPU i7 10700K. The test code is just `1+1 -> 2`. Here are the comparisons.
+I've tested the performance between ``j2v8_win32_x86_64-4.6.0.jar`` and ``j2v8_win32_x86_64-6.2.0.jar`` on a Windows machine with CPU i7 10700K. The test code is just ``1+1 -> 2``. Here are the comparisons.
-| Case | 4.6.0 (TPS) | 6.2.0 (TPS) |
-|--------------------------------|--------------|--------------|
-| Single Session with 1 Thread | 1,003,009 | 1,338,688 |
-| Ad-hoc Session with 1 Thread | 35 | 299 |
-| 4 Sessions with 4 threads | 2,274,019 | 4,571,428 |
+=============================== ============== =============
+ Case 4.6.0 (TPS) 6.2.0 (TPS)
+=============================== ============== =============
+ Single Session with 1 Thread 1,003,009 1,338,688
+ Ad-hoc Session with 1 Thread 35 299
+ 4 Sessions with 4 threads 2,274,019 4,571,428
+=============================== ============== =============
-With this kind of performance improvement, what are the reasons of sticking to `v4.6.0`?
+With this kind of performance improvement, what are the reasons of sticking to ``v4.6.0``?
-### Why Windows and Linux only?
+Why Windows and Linux only?
+===========================
* I don't own a decent Mac device. To be more precisely, I have Mac Mini and MacBook Air, but they are too old (building V8 would take many hours). And I have no plan on buying a new one in the near future. Call for donation? Don't be joking. So there's no MacOS release.
* I don't intend to support Android for now.
-### Why not Automate the J2V8 Build System?
+Why not Automate the J2V8 Build System?
+=======================================
TL;DR: It's too hard.
@@ -65,15 +48,18 @@ TL;DR: It's too hard.
* NodeJS was removed early. I haven't got time reviving it in J2V8.
* J2V8 build system is too old.
* Gradle v2.14.1 is far from the lowest supported gradle version in my latest IntelliJ IDEA. And I don't have interest in installing a legacy Eclipse to play with that version of gradle. Hey, why not upgrade gradle to satisfy IDEA? I tried, but all was bad luck. You may take a try, then understand what I have suffered from.
- * CMake is old and seriously broken on Windows. Nowadays, V8 only supports VS 2017 or 2019, but `CMakeLists.txt` is still at the VS 2015 age. No surprise, it doesn't work at all.
+ * CMake is old and seriously broken on Windows. Nowadays, V8 only supports VS 2017 or 2019, but ``CMakeLists.txt`` is still at the VS 2015 age. No surprise, it doesn't work at all.
* Docker build is deeply broken as well. The dependent docker image was gone. There are many errors in many steps. Sitting there, watching the docker build breaks made me full of frustration because I thought it would take me a few months fixing the problems, but I don't have a few months. No one pays me to do that.
* Python2 scripts form the outer layer of the build system, also hide the actual building logic from someone who tries to fix the build system. I don't want to spend my precious time fixing Python2 scripts, because I've been on Python3 for many years. I wish my hair could be as much as Guido van Rossum's. Obviously, I am not, so no more Python2.
- * Maven is old but the least problematic. At least it allows me to package the jar files with my hack to the `pom.xml`.
+ * Maven is old but the least problematic. At least it allows me to package the jar files with my hack to the ``pom.xml``.
-With these uncertainties, to me, automating the build system is something with ROI closing to 0. Supposing I achieved it in a particular version of V8, let's say v8.3.110.9, it would for sure break in v8.9.213. Yes, I've confirmed that.
+With these uncertainties, to me, automating the build system is something with ROI closing to 0. Supposing I achieved it in a particular version of V8, let's say v8.3.110.9, it would for sure break in v8.9.x. Later, I managed to built v8.9.255 which has been embeded into Javet.
-### Why not Deploy J2V8 to Maven Repository?
+Why not Deploy J2V8 to Maven Repository?
+========================================
* I don't have the permission to its official repository.
* There has been no Windows / Linux releases deployed since 2016 / 2017. I really don't know who to contact with.
* You may easily integrate the jar files in your local maven repository.
+
+[`Home <../../README.rst>`_] [`FAQ `_]
diff --git a/docs/faq/index.rst b/docs/faq/index.rst
new file mode 100644
index 000000000..d010528a6
--- /dev/null
+++ b/docs/faq/index.rst
@@ -0,0 +1,7 @@
+===
+FAQ
+===
+
+* `History with J2V8 `_
+
+[`Home <../../README.rst>`_]
diff --git a/docs/todo_list.rst b/docs/todo_list.rst
new file mode 100644
index 000000000..906c14cb0
--- /dev/null
+++ b/docs/todo_list.rst
@@ -0,0 +1,10 @@
+=========
+TODO List
+=========
+
+* To support more types that are not supported by ECMAScript, e.g. BigDecimal, etc.
+* To revive NodeJS.
+* To implement runtime debugging capability.
+
+
+[`Home <../README.rst>`_]
diff --git a/docs/tutorial/hello_javet.rst b/docs/tutorial/hello_javet.rst
new file mode 100644
index 000000000..71dc4e04b
--- /dev/null
+++ b/docs/tutorial/hello_javet.rst
@@ -0,0 +1,90 @@
+===========
+Hello Javet
+===========
+
+Reference Javet
+===============
+
+Maven
+-----
+
+.. code-block:: xml
+
+
+ com.caoccao.javet
+ javet
+ 0.7.0
+
+
+Gradle Kotlin
+-------------
+
+.. code-block:: kotlin
+
+ dependencies {
+ implementation("com.caoccao.javet:javet:0.7.0")
+ }
+
+Gradle Groovy
+-------------
+
+.. code-block:: groovy
+
+ compile group: 'com.caoccao.javet', name: 'javet', version: '0.7.0'
+
+Print **Hello Javet**
+=====================
+
+.. code-block:: java
+
+ // Step 1: Create a V8 runtime from V8 host in try resource.
+ try (V8Runtime v8Runtime = V8Host.getInstance().createV8Runtime()) {
+ // Step 2: Request a lock.
+ v8Runtime.lock();
+ // Step 3: Execute a string as JavaScript code and print the result to console.
+ System.out.println(v8Runtime.getExecutor("'Hello Javet'").executeString()); // Hello Javet
+ // Step 4: Resource including the lock is recycled automatically at the end of the try resource block.
+ }
+
+Print **1 + 1**
+===============
+
+.. code-block:: java
+
+ // Step 1: Create a V8 runtime from V8 host in try resource.
+ try (V8Runtime v8Runtime = V8Host.getInstance().createV8Runtime()) {
+ // Step 2: Request a lock.
+ v8Runtime.lock();
+ // Step 3: Execute a string as JavaScript code and print the result to console.
+ System.out.println("1 + 1 = " + v8Runtime.getExecutor("1 + 1").executeInteger()); // 2
+ // Step 4: Resource including the lock is recycled automatically at the end of the try resource block.
+ }
+
+Play with Pool and Console
+==========================
+
+.. code-block:: java
+
+ // Create a Javet engine pool.
+ try (IJavetEnginePool javetEnginePool = new JavetEnginePool()) {
+ // Get a Javet engine from the pool.
+ try (IJavetEngine javetEngine = javetEnginePool.getEngine()) {
+ // Get a V8 runtime from the engine.
+ // lock() is not necessary because the Javet engine handles that.
+ V8Runtime v8Runtime = javetEngine.getV8Runtime();
+ // Create a Javet console interceptor.
+ JavetConsoleInterceptor javetConsoleInterceptor = new JavetConsoleInterceptor(v8Runtime);
+ // Register the Javet console to V8 global object.
+ javetConsoleInterceptor.register(v8Runtime.getGlobalObject());
+ // V8 console log is redirected to JVM console log.
+ v8Runtime.getExecutor("console.log('Hello Javet from Pool');").executeVoid();
+ // Unregister the Javet console to V8 global object.
+ javetConsoleInterceptor.unregister(v8Runtime.getGlobalObject());
+ // unlock() is not necessary because the Javet engine handles that.
+ // close() is not necessary because the Javet pool handles that.
+ }
+ }
+
+Please refer to `source code <../../src/test/java/com/caoccao/javet/tutorial/HelloJavet.java>`_ for more detail.
+
+[`Home <../../README.rst>`_] [`Tutorial `_]
diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst
new file mode 100644
index 000000000..eb8575b86
--- /dev/null
+++ b/docs/tutorial/index.rst
@@ -0,0 +1,13 @@
+========
+Tutorial
+========
+
+* `Hello Javet `_
+* `Know the Lock `_
+* `Memory Management `_
+* `Manipulate V8 Function `_
+* `Polyfill `_
+
+Complete tutorial is available at `here <../../src/test/java/com/caoccao/javet/tutorial>`_.
+
+[`Home <../../README.rst>`_]
diff --git a/docs/tutorial/know_the_lock.rst b/docs/tutorial/know_the_lock.rst
new file mode 100644
index 000000000..a9b3b099c
--- /dev/null
+++ b/docs/tutorial/know_the_lock.rst
@@ -0,0 +1,21 @@
+=============
+Know the Lock
+=============
+
+What does Lock Mean in Javet?
+=============================
+
+V8 runtime runs in an isolated and single-threaded environment so that there is no race condition issue. So playing V8 runtime in JVM among multiple threads is prohibited unless the V8 runtime is always protected by **Lock**.
+
+Javet exposed ``lock()`` and ``unlock()`` in ``V8Runtime``. Any attempt of accessing V8 runtime before ``lock()`` or after ``unlock()`` will result in a checked exception reporting lock conflict or V8 runtime closed.
+
+Best Practices
+==============
+
+* Always call ``lock()`` before any access to V8 runtime as well as V8 value objects. Especially:
+ * V8 value reference objects are just Java wrappers of certain JNI native resource, so keeping the lock in effect makes sure V8 threading model is well maintained.
+ * In function callback scenario, the callback needs to access V8 runtime and V8 value objects, so the presence of lock is required.
+* Always keep the lock range as minimal as possible to allow best performance.
+* ``unlock()`` is can be skipped if ``close()`` is called.
+
+[`Home <../../README.rst>`_] [`Tutorial `_]
diff --git a/docs/tutorial/manipulate_v8_function.rst b/docs/tutorial/manipulate_v8_function.rst
new file mode 100644
index 000000000..248d26325
--- /dev/null
+++ b/docs/tutorial/manipulate_v8_function.rst
@@ -0,0 +1,71 @@
+======================
+Manipulate V8 Function
+======================
+
+Lifecycle
+=========
+
+Know the Implication
+--------------------
+
+Lifecycle of a function is recommended to be managed by V8. This is a bit different from the common usage of other V8 value objects.
+
+Why? Because in order to keep track of the callback capability, Javet needs to persist few tiny objects in JVM as well as in V8. Those persisted objects get released immediately when ``close()`` is explicitly called and ``isWeak()`` is ``false``. However, once a function is set to a certain object, it is typically no longer needed. If closing that function explicitly really recycles it, the following callback will cause memory corruption.
+
+The solution is to set the function to weak by ``setWeak()`` so that the lifecycle management is handed over to V8. V8 decides when to recycle the function and notifies Javet to recycle those persisted objects.
+
+Option 1: The Common Way
+------------------------
+
+.. code-block:: java
+
+ // Create a function and wrap it with try resource.
+ try (V8ValueFunction v8ValueFunction = v8Runtime.createV8ValueFunction(v8CallbackContext)) {
+ // Do whatever you want to do with this function
+ }
+ // Outside the code block, this function is no longer valid. Calling this function in V8 will result in memory corruption.
+
+Option 2: The Recommended Way
+-----------------------------
+
+.. code-block:: java
+
+ V8ValueFunction v8ValueFunction = v8Runtime.createV8ValueFunction(v8CallbackContext);
+ // Set this function to the certain V8 value objects.
+ v8ValueFunction.setWeak();
+ // Once this function is set to weak, its lifecycle is automatically managed by Javet + V8.
+ // There is no need to call close() any more.
+
+Automatic Type Conversion
+=========================
+
+Javet is capable of automatically converting its internal ``V8Value`` to other types and that capability can be manipulated by ``JavetConverterUtils`` which also supports custom type conversion. So, the following 4 functions are all the same and valid.
+
+.. code-block:: java
+
+ // Option 1
+ public String echo(String str) {
+ return str;
+ }
+
+ // Option 2
+ public String echo(V8Value arg) {
+ return arg == null ? null : arg.toString();
+ }
+
+ // Option 3
+ public V8Value echo(String str) {
+ return new V8ValueString(str);
+ }
+
+ // Option 4
+ public V8Value echo(V8Value arg) throws JavetException {
+ return arg.toClone();
+ }
+
+ // All 4 functions above can be handled in Javet as the following function
+ echo("123");
+
+Note: Primitive types must be in their object form in the method signature. E.g. ``boolean`` must be set to ``Boolean``, ``int`` must be set to ``Integer``, etc. Why? Because the converted value could be ``null`` which would cause JDK to complain with an exception.
+
+[`Home <../../README.rst>`_] [`Tutorial `_]
diff --git a/docs/tutorial/memory_management.rst b/docs/tutorial/memory_management.rst
new file mode 100644
index 000000000..554b79a93
--- /dev/null
+++ b/docs/tutorial/memory_management.rst
@@ -0,0 +1,62 @@
+=================
+Memory Management
+=================
+
+3 Challenges
+============
+
+JVM GC
+------
+
+JVM is known to have a GC that manages memory automatically. However, that doesn't cover the objects in JNI native implementation. Once ``NewGlobalRef(javaObject)`` is called, that ``javaObject`` lives forever in JVM until ``DeleteGlobalRef(javaObject)`` is called.
+
+C++ Runtime
+-----------
+
+Smart pointers in C++ cannot easily work across JNI to JVM, in other words, raw pointers are directly referenced in JVM as ``long``. C++ runtime has no idea when to free the memory of those raw pointers unless JVM tells C++ runtime to release via JNI.
+
+V8 GC
+-----
+
+V8 generally categorizes objects in memory to 3 types.
+
+1. ``v8::Local`` - It lives within the local scope of a C++ function call.
+2. ``v8::Persistent`` - Its lifecycle is managed by V8 GC.
+3. ``v8::External`` - V8 GC treats it as root object so that it lives as long as the V8 isolate lives.
+
+Solution: Weak Reference
+========================
+
+Javet directly borrows the way V8 manages objects in JVM. The rule is simple in the following 2 patterns.
+
+Manually Manage V8 Objects
+--------------------------
+
+.. code-block:: java
+
+ // Create an object and wrap it with try resource.
+ try (V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) {
+ // Do whatever you want to do with this object
+ // v8ValueObject.close() is called automatically at the end of the block.
+ }
+ // Outside the code block, this object is no longer valid.
+
+Automatically Manage V8 Objects
+-------------------------------
+
+.. code-block:: java
+
+ // Create an object.
+ V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject();
+ // Do whatever you want to do with this object
+ v8ValueObject.setWeak();
+ // Do whatever you want to do with this object
+ /*
+ v8ValueObject.close() is called automatically via V8 GC callback.
+ So, there is no need to close the V8 object explicitly.
+ This is quite useful when the lifecycle is not determined, E.g. V8 function.
+ */
+
+Note: V8 does not recycle objects that are referenced by other objects. Please make sure the object chain is broken so that GC can work as expected. ``com.caoccao.javet.interception.logging.JavetStandardConsoleInterceptor`` is a good sample showing how to deal with that.
+
+[`Home <../../README.rst>`_] [`Tutorial `_]
diff --git a/docs/tutorial/polyfill.rst b/docs/tutorial/polyfill.rst
new file mode 100644
index 000000000..8ee325473
--- /dev/null
+++ b/docs/tutorial/polyfill.rst
@@ -0,0 +1,36 @@
+========
+Polyfill
+========
+
+Yes, you can polyfill Javet with NodeJS modules.
+
+decimal.js
+==========
+
+.. code-block:: java
+
+ public void loadJS() throws JavetException {
+ File decimalJSFile = new File(
+ JavetOSUtils.WORKING_DIRECTORY,
+ "scripts/node/node_modules/decimal.js/decimal.js");
+ if (decimalJSFile.exists() && decimalJSFile.canRead()) {
+ logger.logInfo("Loading {0}.", decimalJSFile.getAbsolutePath());
+ v8Runtime = V8Host.getInstance().createV8Runtime();
+ v8Runtime.lock();
+ v8Runtime.getExecutor(decimalJSFile).executeVoid();
+ } else {
+ logger.logError("{0} is not found.", decimalJSFile.getAbsolutePath());
+ logger.logError("Please make sure NodeJS is installed, then visit script/node directory and run npm install.");
+ }
+ }
+
+ public void test() throws JavetException {
+ logger.logInfo("1.23 + 2.34 = {0}", v8Runtime.getExecutor(
+ "const a = new Decimal(1.23);" +
+ "const b = new Decimal(2.34);" +
+ "a.add(b).toString();").executeString());
+ }
+
+Please refer to `source code <../../src/test/java/com/caoccao/javet/tutorial/DecimalJavet.java>`_ for more detail.
+
+[`Home <../../README.rst>`_] [`Tutorial `_]
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..e708b1c02
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..be52383ef
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 000000000..4f906e0c8
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# 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
+#
+# https://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.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 000000000..107acd32c
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000..0dad72c2d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,191 @@
+
+ 4.0.0
+
+ com.caoccao.javet
+ javet
+ 0.7.0
+ javet
+ Javet is Java + V8 (JAVa + V + EighT). It is a way of embedding V8 in Java.
+ https://github.com/caoccao/Javet
+
+
+
+ APACHE LICENSE, VERSION 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Sam Cao
+ sjtucaocao@gmail.com
+ caoccao.com
+ https://www.caoccao.com
+
+
+
+
+ scm:git:git://github.com/caoccao/Javet.git
+ scm:git:git@github.com:caoccao/caoccao.git
+ https://github.com/caoccao/Javet
+ javet-0.7.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.6.0
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.6.0
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+
+ maven-surefire-plugin
+ 2.22.2
+
+
+ maven-failsafe-plugin
+ 2.22.2
+
+
+ maven-deploy-plugin
+ 3.0.0-M1
+
+
+ default-deploy
+ deploy
+
+ deploy
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.0.0-M1
+
+ true
+ false
+ forked-path
+
+ -Dgpg.passphrase=${gpg.passphrase} -Dmaven.test.skipTests=true -Dmaven.test.skip=true
+
+
+
+ org.apache.maven.scm
+ maven-scm-provider-gitexe
+ 1.11.2
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.2.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.2.0
+
+ UTF-8
+
+
+
+ attach-javadoc
+
+ jar
+
+
+
+
+
+
+
+
+
+
+ release-sign-artifacts
+
+
+ performRelease
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/node/package.json b/scripts/node/package.json
new file mode 100644
index 000000000..c6b6e6651
--- /dev/null
+++ b/scripts/node/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "decimal.js": "^10.2.1"
+ }
+}
diff --git a/scripts/node/test-es5/test-es5-multiline-string-literals.js b/scripts/node/test-es5/test-es5-multiline-string-literals.js
new file mode 100644
index 000000000..dfda0b904
--- /dev/null
+++ b/scripts/node/test-es5/test-es5-multiline-string-literals.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f() {
+ const x = 123;
+ const result = `aaa${x}bbb`;
+ console.log(result);
+ return result;
+}
+
+f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-array-find-index.js b/scripts/node/test-es6/test-es6-array-find-index.js
new file mode 100644
index 000000000..2585afe8d
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-array-find-index.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function x(value, index, array) {
+ return value > 2;
+}
+
+function f() {
+ const result = [1,2,3].findIndex(x);
+ console.log(result);
+ return result;
+}
+
+f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-array-find.js b/scripts/node/test-es6/test-es6-array-find.js
new file mode 100644
index 000000000..6c25187bf
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-array-find.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function x(value, index, array) {
+ return value > 2;
+}
+
+function f() {
+ const result = [1,2,3].find(x);
+ console.log(result);
+ return result;
+}
+
+f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-arrow-function.js b/scripts/node/test-es6/test-es6-arrow-function.js
new file mode 100644
index 000000000..2160c9f4b
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-arrow-function.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+const f = () => {
+ const x = 1;
+ let y = 2;
+ const result = x + y;
+ console.log(result);
+ return result;
+}
+
+f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-class.js b/scripts/node/test-es6/test-es6-class.js
new file mode 100644
index 000000000..5a21e1ea9
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-class.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+class A {
+ constructor() {
+ this.x = 1;
+ this.y = 2;
+ }
+
+ f() {
+ const result = this.x + this.y;
+ console.log(result);
+ return result;
+ }
+}
+
+const a = new A();
+a.f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-default-parameter-values.js b/scripts/node/test-es6/test-es6-default-parameter-values.js
new file mode 100644
index 000000000..84a1189e9
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-default-parameter-values.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f(x = 1, y = 2)
+{
+ const result = x + y;
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/node/test-es6/test-es6-function-rest-parameter.js b/scripts/node/test-es6/test-es6-function-rest-parameter.js
new file mode 100644
index 000000000..5e5c3fbad
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-function-rest-parameter.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f(...args) {
+ let result = 0;
+ for (let arg of args) result += arg;
+ console.log(result);
+ return result;
+}
+
+f(1,2,3);
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-is-finite.js b/scripts/node/test-es6/test-es6-is-finite.js
new file mode 100644
index 000000000..481250066
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-is-finite.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f()
+{
+ const result = [isFinite(10/1), isFinite(10/0)];
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/node/test-es6/test-es6-is-nan.js b/scripts/node/test-es6/test-es6-is-nan.js
new file mode 100644
index 000000000..2fe4ee8b7
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-is-nan.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f()
+{
+ const result = [isNaN(NaN), isNaN("123")];
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/node/test-es6/test-es6-let-const.js b/scripts/node/test-es6/test-es6-let-const.js
new file mode 100644
index 000000000..ad9070783
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-let-const.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f() {
+ const x = 1;
+ let y = 2;
+ const result = x + y;
+ console.log(result);
+ return result;
+}
+
+f();
\ No newline at end of file
diff --git a/scripts/node/test-es6/test-es6-number-is-integer.js b/scripts/node/test-es6/test-es6-number-is-integer.js
new file mode 100644
index 000000000..b83f06e12
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-number-is-integer.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f()
+{
+ const result = [Number.isInteger(1), Number.isInteger(1.5)];
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/node/test-es6/test-es6-number-is-safe-integer.js b/scripts/node/test-es6/test-es6-number-is-safe-integer.js
new file mode 100644
index 000000000..02c4f6f7d
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-number-is-safe-integer.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f()
+{
+ const result = [Number.isSafeInteger(1), Number.isSafeInteger(12345678901234567890)];
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/node/test-es6/test-es6-symbol.js b/scripts/node/test-es6/test-es6-symbol.js
new file mode 100644
index 000000000..f36a64ac8
--- /dev/null
+++ b/scripts/node/test-es6/test-es6-symbol.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 caoccao.com Sam Cao
+ * All rights reserved.
+
+ * 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.
+ */
+
+"use strict";
+
+function f()
+{
+ const result = Symbol("id") == Symbol("id");
+ console.log(result);
+ return result;
+}
+
+f();
diff --git a/scripts/python/change_javet_version.py b/scripts/python/change_javet_version.py
new file mode 100644
index 000000000..a672f5288
--- /dev/null
+++ b/scripts/python/change_javet_version.py
@@ -0,0 +1,96 @@
+'''
+ Copyright (c) 2021 caoccao.com Sam Cao
+ All rights reserved.
+
+ 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.
+'''
+
+import coloredlogs
+import logging
+import pathlib
+import re
+import sys
+
+coloredlogs.install(level=logging.DEBUG, fmt='%(asctime)-15s %(name)s %(levelname)s: %(message)s')
+
+class ChangeJavetVersion(object):
+
+ def __init__(self, version) -> None:
+ self._root_path = (pathlib.Path(__file__) / '../../../').resolve().absolute()
+ self._version = version
+
+ def update(self):
+ self._update(
+ 'README.rst', '\n',
+ re.compile(r'\*(?P\d+\.\d+\.\d+)\*'),
+ re.compile(r'^ (?P\d+\.\d+\.\d+) $'),
+ re.compile(r'javet:(?P\d+\.\d+\.\d+)"'),
+ re.compile(r'version: \'(?P\d+\.\d+\.\d+)\''))
+ self._update(
+ 'build.gradle.kts', '\n',
+ re.compile(r'^version = "(?P\d+\.\d+\.\d+)"$'))
+ self._update(
+ 'docs/tutorial/hello_javet.rst', '\n',
+ re.compile(r'^ (?P\d+\.\d+\.\d+) $'),
+ re.compile(r'javet:(?P\d+\.\d+\.\d+)"'),
+ re.compile(r'version: \'(?P\d+\.\d+\.\d+)\''))
+ self._update(
+ 'pom.xml', '\n',
+ re.compile(r'^ (?P\d+\.\d+\.\d+) $'))
+ self._update(
+ 'cpp/build.cmd', '\n',
+ re.compile(r'JAVET_VERSION=(?P\d+\.\d+\.\d+)$'))
+ self._update(
+ 'cpp/build.sh', '\n',
+ re.compile(r'JAVET_VERSION=(?P\d+\.\d+\.\d+)$'))
+ self._update(
+ 'src/main/java/com/caoccao/javet/interop/JavetLibLoader.java', '\n',
+ re.compile(r'LIB_VERSION = "(?P\d+\.\d+\.\d+)";$'))
+ self._update(
+ 'cpp/jni/javet.rc', '\n',
+ re.compile(r'"(?P\d+\.\d+\.\d+)'),
+ re.compile(r'v\.(?P\d+\.\d+\.\d+)'),
+ re.compile(r'(?P\d+,\d+,\d+)'))
+
+ def _update(self, relative_file_path: str, line_separator: str, *patterns: list):
+ file_path = (self._root_path / relative_file_path).resolve().absolute()
+ logging.info('Updating %s.', str(file_path))
+ lines, line_number = [], 1
+ for line in file_path.read_text('utf-8').split(line_separator):
+ for pattern in patterns:
+ match_object = pattern.search(line)
+ if match_object is not None:
+ version = self._version
+ if ',' in match_object.group('version'):
+ version = version.replace('.', ',')
+ logging.info(
+ ' %d: %s -> %s',
+ line_number,
+ match_object.group('version'),
+ version)
+ line = '{prefix}{version}{suffix}'.format(
+ prefix=line[:match_object.start('version')],
+ version=version,
+ suffix=line[match_object.end('version'):])
+ break
+ lines.append(line)
+ line_number += 1
+ file_path.write_text(line_separator.join(lines), 'utf-8')
+
+def main():
+ change_javet_version = ChangeJavetVersion('0.7.0')
+ change_javet_version.update()
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(int(main() or 0))
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 000000000..ba720289c
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.
+ *
+ */
+
+rootProject.name = "javet"
diff --git a/src/main/java/com/caoccao/javet/exceptions/BaseJavetScriptingException.java b/src/main/java/com/caoccao/javet/exceptions/BaseJavetScriptingException.java
new file mode 100644
index 000000000..3d04b58d2
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/BaseJavetScriptingException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public abstract class BaseJavetScriptingException extends JavetException {
+ protected JavetScriptingError error;
+
+ public BaseJavetScriptingException(
+ String message, String resourceName, String sourceLine,
+ int lineNumber, int startColumn, int endColumn, int startPosition, int endPosition) {
+ super(message);
+ error = new JavetScriptingError(message, resourceName, sourceLine,
+ lineNumber, startColumn, endColumn, startPosition, endPosition);
+ }
+
+ public JavetScriptingError getError() {
+ return error;
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetCompilationException.java b/src/main/java/com/caoccao/javet/exceptions/JavetCompilationException.java
new file mode 100644
index 000000000..81c625f4a
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetCompilationException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetCompilationException extends BaseJavetScriptingException {
+ public JavetCompilationException(
+ String message, String resourceName, String sourceLine,
+ int lineNumber, int startColumn, int endColumn, int startPosition, int endPosition) {
+ super(message, resourceName, sourceLine, lineNumber, startColumn, endColumn, startPosition, endPosition);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetConverterException.java b/src/main/java/com/caoccao/javet/exceptions/JavetConverterException.java
new file mode 100644
index 000000000..cb37a0a90
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetConverterException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetConverterException extends JavetException {
+ public JavetConverterException(String message) {
+ super(MessageFormat.format("Failed to convert values with error message {0}", message));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetException.java b/src/main/java/com/caoccao/javet/exceptions/JavetException.java
new file mode 100644
index 000000000..85330832d
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetException extends Exception {
+ public JavetException() {
+ super();
+ }
+
+ public JavetException(String message) {
+ super(message);
+ }
+
+ public JavetException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public JavetException(Throwable cause) {
+ super(cause);
+ }
+
+ public JavetException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetExecutionException.java b/src/main/java/com/caoccao/javet/exceptions/JavetExecutionException.java
new file mode 100644
index 000000000..bdf5d17fb
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetExecutionException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetExecutionException extends BaseJavetScriptingException {
+ public JavetExecutionException(
+ String message, String resourceName, String sourceLine,
+ int lineNumber, int startColumn, int endColumn, int startPosition, int endPosition) {
+ super(message, resourceName, sourceLine, lineNumber, startColumn, endColumn, startPosition, endPosition);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetIOException.java b/src/main/java/com/caoccao/javet/exceptions/JavetIOException.java
new file mode 100644
index 000000000..c8aa2403f
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetIOException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.nio.file.Path;
+import java.text.MessageFormat;
+
+public class JavetIOException extends JavetException {
+ private JavetIOException(String message) {
+ super(message);
+ }
+
+ private JavetIOException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public static JavetIOException failedToReadPath(Path path, Throwable cause) {
+ return new JavetIOException(
+ MessageFormat.format("Failed to read {0}", path.toFile().getAbsolutePath()), cause);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetNotSupportedException.java b/src/main/java/com/caoccao/javet/exceptions/JavetNotSupportedException.java
new file mode 100644
index 000000000..09d4c2b1b
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetNotSupportedException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetNotSupportedException extends JavetException {
+ public JavetNotSupportedException(String feature) {
+ super(MessageFormat.format("{0} is not supported", feature));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetOSNotSupportedException.java b/src/main/java/com/caoccao/javet/exceptions/JavetOSNotSupportedException.java
new file mode 100644
index 000000000..3257bdb2b
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetOSNotSupportedException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetOSNotSupportedException extends JavetException {
+ public JavetOSNotSupportedException(String osName) {
+ super(MessageFormat.format("OS [{0}] is not supported.", osName));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetScriptingError.java b/src/main/java/com/caoccao/javet/exceptions/JavetScriptingError.java
new file mode 100644
index 000000000..bcacc9b5e
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetScriptingError.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public final class JavetScriptingError {
+ private String message;
+ private String resourceName;
+ private String sourceLine;
+ private int lineNumber;
+ private int startColumn;
+ private int endColumn;
+ private int startPosition;
+ private int endPosition;
+
+ public JavetScriptingError(
+ String message, String resourceName, String sourceLine,
+ int lineNumber, int startColumn, int endColumn, int startPosition, int endPosition) {
+ this.message = message;
+ this.resourceName = resourceName;
+ this.sourceLine = sourceLine;
+ this.lineNumber = lineNumber;
+ this.startColumn = startColumn;
+ this.endColumn = endColumn;
+ this.startPosition = startPosition;
+ this.endPosition = endPosition;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ public void setResourceName(String resourceName) {
+ this.resourceName = resourceName;
+ }
+
+ public String getSourceLine() {
+ return sourceLine;
+ }
+
+ public void setSourceLine(String sourceLine) {
+ this.sourceLine = sourceLine;
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ public void setLineNumber(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
+ public int getStartColumn() {
+ return startColumn;
+ }
+
+ public void setStartColumn(int startColumn) {
+ this.startColumn = startColumn;
+ }
+
+ public int getEndColumn() {
+ return endColumn;
+ }
+
+ public void setEndColumn(int endColumn) {
+ this.endColumn = endColumn;
+ }
+
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ public void setStartPosition(int startPosition) {
+ this.startPosition = startPosition;
+ }
+
+ public int getEndPosition() {
+ return endPosition;
+ }
+
+ public void setEndPosition(int endPosition) {
+ this.endPosition = endPosition;
+ }
+
+ @Override
+ public String toString() {
+ return MessageFormat.format(
+ "Error: {0}\nResource: {1}\nSource Code: {2}\nLine Number: {3}\nColumn: {4}, {5}\nPosition: {6}, {7}",
+ message, resourceName, sourceLine, Integer.toString(lineNumber),
+ Integer.toString(startColumn), Integer.toString(endColumn),
+ Integer.toString(startPosition), Integer.toString(endPosition));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetUnknownCompilationException.java b/src/main/java/com/caoccao/javet/exceptions/JavetUnknownCompilationException.java
new file mode 100644
index 000000000..841c306bf
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetUnknownCompilationException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetUnknownCompilationException extends JavetException {
+ public JavetUnknownCompilationException(String message) {
+ super(MessageFormat.format("Unknown compilation error {0}", message));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetUnknownExecutionException.java b/src/main/java/com/caoccao/javet/exceptions/JavetUnknownExecutionException.java
new file mode 100644
index 000000000..9f6ccdac6
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetUnknownExecutionException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetUnknownExecutionException extends JavetException {
+ public JavetUnknownExecutionException(String message) {
+ super(MessageFormat.format("Unknown execution error {0}", message));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackAlreadyRegisteredException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackAlreadyRegisteredException.java
new file mode 100644
index 000000000..62c989635
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackAlreadyRegisteredException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8CallbackAlreadyRegisteredException extends JavetException {
+ public JavetV8CallbackAlreadyRegisteredException() {
+ super("V8 callback is already registered");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackNotRegisteredException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackNotRegisteredException.java
new file mode 100644
index 000000000..3d2349adf
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackNotRegisteredException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8CallbackNotRegisteredException extends JavetException {
+ public JavetV8CallbackNotRegisteredException() {
+ super("V8 callback is not registered");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackSignatureMismatchException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackSignatureMismatchException.java
new file mode 100644
index 000000000..d5881dc83
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8CallbackSignatureMismatchException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetV8CallbackSignatureMismatchException extends JavetException {
+ protected JavetV8CallbackSignatureMismatchException(String format, Object... objects) {
+ super(MessageFormat.format("V8 callback signature mismatches: " + format, objects));
+ }
+
+ protected JavetV8CallbackSignatureMismatchException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public static JavetV8CallbackSignatureMismatchException parameterSizeMismatch(
+ int expectedSize, int actualSize) {
+ return new JavetV8CallbackSignatureMismatchException(
+ "expected parameter size is {0}, actual parameter size is {1}",
+ expectedSize, actualSize);
+ }
+
+ public static JavetV8CallbackSignatureMismatchException parameterTypeMismatch(
+ Class expectedType, Class actualType) {
+ return new JavetV8CallbackSignatureMismatchException(
+ "expected parameter type is {0}, actual parameter type is {1}",
+ expectedType.getName(), actualType.getName());
+ }
+
+ public static JavetV8CallbackSignatureMismatchException unknown(
+ Throwable cause) {
+ return new JavetV8CallbackSignatureMismatchException(cause.getMessage(), cause);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyClosedException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyClosedException.java
new file mode 100644
index 000000000..7f5369854
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyClosedException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8RuntimeAlreadyClosedException extends JavetException {
+ public JavetV8RuntimeAlreadyClosedException() {
+ super("V8 runtime is already closed");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyRegisteredException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyRegisteredException.java
new file mode 100644
index 000000000..e59b7baa6
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeAlreadyRegisteredException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8RuntimeAlreadyRegisteredException extends JavetException {
+ public JavetV8RuntimeAlreadyRegisteredException() {
+ super("V8 runtime is already registered");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLeakException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLeakException.java
new file mode 100644
index 000000000..a033654c6
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLeakException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetV8RuntimeLeakException extends JavetException {
+ public JavetV8RuntimeLeakException(int count) {
+ super(MessageFormat.format("{0} V8 runtime(s) leaked", Integer.toString(count)));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLockConflictException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLockConflictException.java
new file mode 100644
index 000000000..ac5ba768b
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeLockConflictException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+import java.text.MessageFormat;
+
+public class JavetV8RuntimeLockConflictException extends JavetException {
+ public JavetV8RuntimeLockConflictException(String message) {
+ super(message);
+ }
+
+ public JavetV8RuntimeLockConflictException() {
+ this("V8 runtime lock conflict is detected");
+ }
+
+ public JavetV8RuntimeLockConflictException(long lockedThreadId, long currentThreadId) {
+ this(MessageFormat.format(
+ "V8 runtime lock conflict is detected with locked thread ID {0} and current thread ID {1}",
+ Long.toString(lockedThreadId), Long.toString(currentThreadId)));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeNotRegisteredException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeNotRegisteredException.java
new file mode 100644
index 000000000..5e1ddd2af
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8RuntimeNotRegisteredException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8RuntimeNotRegisteredException extends JavetException {
+ public JavetV8RuntimeNotRegisteredException() {
+ super("V8 runtime is not registered");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetV8ValueAlreadyClosedException.java b/src/main/java/com/caoccao/javet/exceptions/JavetV8ValueAlreadyClosedException.java
new file mode 100644
index 000000000..4f6eba68b
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/exceptions/JavetV8ValueAlreadyClosedException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.exceptions;
+
+public class JavetV8ValueAlreadyClosedException extends JavetException {
+ public JavetV8ValueAlreadyClosedException() {
+ super("V8 value is already closed");
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interception/BaseJavetInterceptor.java b/src/main/java/com/caoccao/javet/interception/BaseJavetInterceptor.java
new file mode 100644
index 000000000..fd52f446f
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interception/BaseJavetInterceptor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interception;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.interfaces.IJavetInterceptor;
+import com.caoccao.javet.interop.IV8CallbackReceiver;
+import com.caoccao.javet.interop.V8Runtime;
+import com.caoccao.javet.values.reference.IV8ValueObject;
+
+public abstract class BaseJavetInterceptor implements IJavetInterceptor, IV8CallbackReceiver {
+ protected V8Runtime v8Runtime;
+
+ public BaseJavetInterceptor(V8Runtime v8Runtime) {
+ this.v8Runtime = v8Runtime;
+ }
+
+ @Override
+ public abstract boolean register(IV8ValueObject iV8ValueObject) throws JavetException;
+
+ @Override
+ public abstract boolean unregister(IV8ValueObject iV8ValueObject) throws JavetException;
+
+ @Override
+ public V8Runtime getV8Runtime() {
+ return v8Runtime;
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interception/logging/BaseJavetConsoleInterceptor.java b/src/main/java/com/caoccao/javet/interception/logging/BaseJavetConsoleInterceptor.java
new file mode 100644
index 000000000..c4ae9ff1f
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interception/logging/BaseJavetConsoleInterceptor.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interception.logging;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.exceptions.JavetV8CallbackSignatureMismatchException;
+import com.caoccao.javet.interception.BaseJavetInterceptor;
+import com.caoccao.javet.interop.V8Runtime;
+import com.caoccao.javet.utils.V8CallbackContext;
+import com.caoccao.javet.values.V8Value;
+import com.caoccao.javet.values.reference.IV8ValueObject;
+import com.caoccao.javet.values.reference.V8ValueFunction;
+import com.caoccao.javet.values.reference.V8ValueObject;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public abstract class BaseJavetConsoleInterceptor extends BaseJavetInterceptor {
+ protected static final String JS_FUNCTION_DEBUG = "debug";
+ protected static final String JS_FUNCTION_ERROR = "error";
+ protected static final String JS_FUNCTION_INFO = "info";
+ protected static final String JS_FUNCTION_LOG = "log";
+ protected static final String JS_FUNCTION_TRACE = "trace";
+ protected static final String JS_FUNCTION_WARN = "warn";
+ protected static final String JAVA_CONSOLE_DEBUG = "consoleDebug";
+ protected static final String JAVA_CONSOLE_ERROR = "consoleError";
+ protected static final String JAVA_CONSOLE_INFO = "consoleInfo";
+ protected static final String JAVA_CONSOLE_LOG = "consoleLog";
+ protected static final String JAVA_CONSOLE_TRACE = "consoleTrace";
+ protected static final String JAVA_CONSOLE_WARN = "consoleWarn";
+ protected static final String EMPTY = "";
+ protected static final String SPACE = " ";
+ protected static final String PROPERTY_CONSOLE = "console";
+
+ public BaseJavetConsoleInterceptor(V8Runtime v8Runtime) {
+ super(v8Runtime);
+ }
+
+ protected String concat(V8Value... v8Values) {
+ if (v8Values == null || v8Values.length == 0) {
+ return EMPTY;
+ }
+ return String.join(
+ SPACE,
+ Arrays.stream(v8Values).map(v8Value -> v8Value.toString()).collect(Collectors.toList()));
+ }
+
+ public abstract void consoleDebug(V8Value... v8Values);
+
+ public abstract void consoleError(V8Value... v8Values);
+
+ public abstract void consoleInfo(V8Value... v8Values);
+
+ public abstract void consoleLog(V8Value... v8Values);
+
+ public abstract void consoleTrace(V8Value... v8Values);
+
+ public abstract void consoleWarn(V8Value... v8Values);
+
+ @Override
+ public boolean register(IV8ValueObject iV8ValueObject) throws JavetException {
+ try (V8ValueObject console = v8Runtime.createV8ValueObject()) {
+ iV8ValueObject.set(PROPERTY_CONSOLE, console);
+ register(console, JS_FUNCTION_DEBUG, JAVA_CONSOLE_DEBUG);
+ register(console, JS_FUNCTION_ERROR, JAVA_CONSOLE_ERROR);
+ register(console, JS_FUNCTION_INFO, JAVA_CONSOLE_INFO);
+ register(console, JS_FUNCTION_LOG, JAVA_CONSOLE_LOG);
+ register(console, JS_FUNCTION_TRACE, JAVA_CONSOLE_TRACE);
+ register(console, JS_FUNCTION_WARN, JAVA_CONSOLE_WARN);
+ return true;
+ } catch (NoSuchMethodException e) {
+ throw JavetV8CallbackSignatureMismatchException.unknown(e);
+ }
+ }
+
+ protected void register(IV8ValueObject iV8ValueObject, String jsFunctionName, String javaFunctionName)
+ throws JavetException, NoSuchMethodException {
+ V8CallbackContext callbackContext = new V8CallbackContext(
+ this, getClass().getMethod(javaFunctionName, V8Value[].class));
+ V8ValueFunction v8ValueFunction = v8Runtime.createV8ValueFunction(callbackContext);
+ iV8ValueObject.set(jsFunctionName, v8ValueFunction);
+ v8ValueFunction.setWeak();
+ }
+
+ @Override
+ public boolean unregister(IV8ValueObject iV8ValueObject) throws JavetException {
+ return iV8ValueObject.delete(PROPERTY_CONSOLE);
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interception/logging/JavetStandardConsoleInterceptor.java b/src/main/java/com/caoccao/javet/interception/logging/JavetStandardConsoleInterceptor.java
new file mode 100644
index 000000000..db58c72d1
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interception/logging/JavetStandardConsoleInterceptor.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interception.logging;
+
+import com.caoccao.javet.interop.V8Runtime;
+import com.caoccao.javet.values.V8Value;
+
+import java.io.PrintStream;
+
+public class JavetStandardConsoleInterceptor extends BaseJavetConsoleInterceptor {
+ protected PrintStream debug;
+ protected PrintStream error;
+ protected PrintStream info;
+ protected PrintStream log;
+ protected PrintStream trace;
+ protected PrintStream warn;
+
+ public JavetStandardConsoleInterceptor(V8Runtime v8Runtime) {
+ super(v8Runtime);
+ debug = info = log = trace = warn = System.out;
+ error = System.err;
+ }
+
+ public PrintStream getDebug() {
+ return debug;
+ }
+
+ public void setDebug(PrintStream debug) {
+ this.debug = debug;
+ }
+
+ public PrintStream getError() {
+ return error;
+ }
+
+ public void setError(PrintStream error) {
+ this.error = error;
+ }
+
+ public PrintStream getInfo() {
+ return info;
+ }
+
+ public void setInfo(PrintStream info) {
+ this.info = info;
+ }
+
+ public PrintStream getLog() {
+ return log;
+ }
+
+ public void setLog(PrintStream log) {
+ this.log = log;
+ }
+
+ public PrintStream getTrace() {
+ return trace;
+ }
+
+ public void setTrace(PrintStream trace) {
+ this.trace = trace;
+ }
+
+ public PrintStream getWarn() {
+ return warn;
+ }
+
+ public void setWarn(PrintStream warn) {
+ this.warn = warn;
+ }
+
+ @Override
+ public void consoleDebug(V8Value... v8Values) {
+ debug.println(concat(v8Values));
+ }
+
+ @Override
+ public void consoleError(V8Value... v8Values) {
+ error.println(concat(v8Values));
+ }
+
+ @Override
+ public void consoleInfo(V8Value... v8Values) {
+ info.println(concat(v8Values));
+ }
+
+ @Override
+ public void consoleLog(V8Value... v8Values) {
+ log.println(concat(v8Values));
+ }
+
+ @Override
+ public void consoleTrace(V8Value... v8Values) {
+ trace.println(concat(v8Values));
+ }
+
+ @Override
+ public void consoleWarn(V8Value... v8Values) {
+ warn.println(concat(v8Values));
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interfaces/IJavetClosable.java b/src/main/java/com/caoccao/javet/interfaces/IJavetClosable.java
new file mode 100644
index 000000000..26c25082f
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interfaces/IJavetClosable.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.interfaces;
+
+import com.caoccao.javet.exceptions.JavetException;
+
+public interface IJavetClosable extends AutoCloseable {
+ void close() throws JavetException;
+}
diff --git a/src/main/java/com/caoccao/javet/interfaces/IJavetInterceptor.java b/src/main/java/com/caoccao/javet/interfaces/IJavetInterceptor.java
new file mode 100644
index 000000000..90a3ece54
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interfaces/IJavetInterceptor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interfaces;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.values.reference.IV8ValueObject;
+
+public interface IJavetInterceptor {
+ boolean register(IV8ValueObject iV8ValueObject) throws JavetException;
+
+ boolean unregister(IV8ValueObject iV8ValueObject) throws JavetException;
+}
diff --git a/src/main/java/com/caoccao/javet/interfaces/IJavetLogger.java b/src/main/java/com/caoccao/javet/interfaces/IJavetLogger.java
new file mode 100644
index 000000000..1e55d6053
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interfaces/IJavetLogger.java
@@ -0,0 +1,35 @@
+package com.caoccao.javet.interfaces;
+
+import java.text.MessageFormat;
+
+public interface IJavetLogger {
+ void debug(String message);
+
+ void error(String message);
+
+ void error(Throwable cause, String message);
+
+ void info(String message);
+
+ default void logDebug(String format, Object... objects) {
+ debug(MessageFormat.format(format, objects));
+ }
+
+ default void logError(Throwable cause, String format, Object... objects) {
+ error(cause, MessageFormat.format(format, objects));
+ }
+
+ default void logError(String format, Object... objects) {
+ error(MessageFormat.format(format, objects));
+ }
+
+ default void logInfo(String format, Object... objects) {
+ info(MessageFormat.format(format, objects));
+ }
+
+ default void logWarn(String format, Object... objects) {
+ warn(MessageFormat.format(format, objects));
+ }
+
+ void warn(String message);
+}
diff --git a/src/main/java/com/caoccao/javet/interfaces/IJavetResettable.java b/src/main/java/com/caoccao/javet/interfaces/IJavetResettable.java
new file mode 100644
index 000000000..8a5bac2f8
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interfaces/IJavetResettable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.interfaces;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.exceptions.JavetV8RuntimeAlreadyClosedException;
+import com.caoccao.javet.exceptions.JavetV8RuntimeLockConflictException;
+
+public interface IJavetResettable {
+ void reset() throws JavetException;
+}
diff --git a/src/main/java/com/caoccao/javet/interop/IV8CallbackReceiver.java b/src/main/java/com/caoccao/javet/interop/IV8CallbackReceiver.java
new file mode 100644
index 000000000..609bcdecb
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/IV8CallbackReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interop;
+
+public interface IV8CallbackReceiver {
+ V8Runtime getV8Runtime();
+}
diff --git a/src/main/java/com/caoccao/javet/interop/IV8Cloneable.java b/src/main/java/com/caoccao/javet/interop/IV8Cloneable.java
new file mode 100644
index 000000000..42e442563
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/IV8Cloneable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interop;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.values.V8Value;
+
+@SuppressWarnings("unchecked")
+public interface IV8Cloneable {
+ T toClone() throws JavetException;
+}
diff --git a/src/main/java/com/caoccao/javet/interop/IV8Creatable.java b/src/main/java/com/caoccao/javet/interop/IV8Creatable.java
new file mode 100644
index 000000000..a0813981d
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/IV8Creatable.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interop;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.utils.V8CallbackContext;
+import com.caoccao.javet.values.reference.*;
+
+import java.lang.reflect.Method;
+
+public interface IV8Creatable {
+ V8ValueArray createV8ValueArray() throws JavetException;
+
+ V8ValueFunction createV8ValueFunction(V8CallbackContext v8CallbackContext) throws JavetException;
+
+ V8ValueMap createV8ValueMap() throws JavetException;
+
+ V8ValueObject createV8ValueObject() throws JavetException;
+
+ V8ValueSet createV8ValueSet() throws JavetException;
+}
diff --git a/src/main/java/com/caoccao/javet/interop/IV8Executable.java b/src/main/java/com/caoccao/javet/interop/IV8Executable.java
new file mode 100644
index 000000000..22c59abe5
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/IV8Executable.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interop;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.interop.executors.IV8Executor;
+import com.caoccao.javet.values.V8Value;
+
+import java.io.File;
+import java.nio.file.Path;
+
+@SuppressWarnings("unchecked")
+public interface IV8Executable {
+ void compileOnly(String scriptString, V8ScriptOrigin v8ScriptOrigin) throws JavetException;
+
+ T execute(
+ String scriptString, V8ScriptOrigin v8ScriptOrigin, boolean resultRequired) throws JavetException;
+
+ default IV8Executor getExecutor(File scriptFile) {
+ return getExecutor(scriptFile.toPath());
+ }
+
+ IV8Executor getExecutor(Path scriptPath);
+
+ IV8Executor getExecutor(String scriptString);
+}
diff --git a/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java b/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java
new file mode 100644
index 000000000..d1b1b84eb
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.interop;
+
+import com.caoccao.javet.exceptions.JavetIOException;
+import com.caoccao.javet.exceptions.JavetOSNotSupportedException;
+import com.caoccao.javet.utils.JavetDefaultLogger;
+import com.caoccao.javet.utils.JavetOSUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+
+final class JavetLibLoader {
+ private static final String CHMOD = "chmod";
+ private static final String XRR = "755";
+ private static final String LIB_VERSION = "0.7.0";
+ private static final String LIB_FILE_NAME_FORMAT = "libjavet-{0}-x86_64.v.{1}.{2}";
+ private static final String RESOURCE_NAME_FORMAT = "/{0}";
+ private static final String LIB_FILE_EXTENSION_LINUX = "so";
+ private static final String LIB_FILE_EXTENSION_WINDOWS = "dll";
+ private static final String OS_LINUX = "linux";
+ private static final String OS_WINDOWS = "windows";
+ private static int BUFFER_LENGTH = 4096;
+
+ private static Object lockObject = new Object();
+ private static boolean javetLibLoaded = false;
+
+ private JavetLibLoader() {
+ }
+
+ static boolean load() throws JavetOSNotSupportedException, JavetIOException {
+ if (!javetLibLoaded) {
+ synchronized (lockObject) {
+ if (!javetLibLoaded) {
+ internalLoad();
+ javetLibLoaded = true;
+ }
+ }
+ }
+ return javetLibLoaded;
+ }
+
+ private static boolean deployLibFile(File libFile) {
+ boolean isDeployed = false;
+ boolean isLibFileLocked = false;
+ if (libFile.exists()) {
+ try {
+ libFile.delete();
+ } catch (Exception e) {
+ isLibFileLocked = true;
+ }
+ }
+ if (!isLibFileLocked) {
+ byte[] buffer = new byte[BUFFER_LENGTH];
+ String resourceName = MessageFormat.format(RESOURCE_NAME_FORMAT, libFile.getName());
+ try (InputStream inputStream = JavetLibLoader.class.getResourceAsStream(resourceName);
+ FileOutputStream outputStream = new FileOutputStream(libFile.getAbsolutePath())) {
+ while (true) {
+ int length = inputStream.read(buffer);
+ if (length == -1) {
+ break;
+ }
+ outputStream.write(buffer, 0, length);
+ }
+ isDeployed = true;
+ } catch (Exception e) {
+ // Lib file is locked.
+ }
+ if (isDeployed && JavetOSUtils.IS_LINUX) {
+ try {
+ Runtime.getRuntime().exec(new String[]{CHMOD, XRR, libFile.getAbsolutePath()}).waitFor();
+ } catch (Throwable e) {
+ }
+ }
+ }
+ return isDeployed;
+ }
+
+ private static File getLibFile(String rootDirectory) throws JavetOSNotSupportedException {
+ if (JavetOSUtils.IS_WINDOWS) {
+ return new File(
+ rootDirectory,
+ MessageFormat.format(
+ LIB_FILE_NAME_FORMAT,
+ OS_WINDOWS, LIB_VERSION, LIB_FILE_EXTENSION_WINDOWS));
+ } else if (JavetOSUtils.IS_LINUX) {
+ return new File(
+ rootDirectory,
+ MessageFormat.format(
+ LIB_FILE_NAME_FORMAT,
+ OS_LINUX, LIB_VERSION, LIB_FILE_EXTENSION_LINUX));
+ } else {
+ throw new JavetOSNotSupportedException(JavetOSUtils.OS_NAME);
+ }
+ }
+
+ private static void internalLoad() throws JavetOSNotSupportedException, JavetIOException {
+ File tempDirectoryLibFile = getLibFile(JavetOSUtils.TEMP_DIRECTORY);
+ try {
+ deployLibFile(tempDirectoryLibFile);
+ System.load(tempDirectoryLibFile.getAbsolutePath());
+ } catch (Throwable t) {
+ throw JavetIOException.failedToReadPath(tempDirectoryLibFile.toPath(), t);
+ }
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interop/V8Flags.java b/src/main/java/com/caoccao/javet/interop/V8Flags.java
new file mode 100644
index 000000000..cae51d063
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/V8Flags.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021. caoccao.com Sam Cao
+ * All rights reserved.
+ *
+ * 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.caoccao.javet.interop;
+
+public final class V8Flags {
+ private boolean allowNativesSyntax;
+ private boolean exposeGC;
+ private boolean sealed;
+ private boolean trackRetainingPath;
+ private boolean useStrict;
+
+ V8Flags() {
+ allowNativesSyntax = false;
+ exposeGC = false;
+ sealed = false;
+ trackRetainingPath = false;
+ useStrict = true;
+ }
+
+ public boolean isTrackRetainingPath() {
+ return trackRetainingPath;
+ }
+
+ public void setTrackRetainingPath(boolean trackRetainingPath) {
+ if (!sealed) {
+ this.trackRetainingPath = trackRetainingPath;
+ }
+ }
+
+ public boolean isSealed() {
+ return sealed;
+ }
+
+ public void seal() {
+ if (!sealed) {
+ sealed = true;
+ }
+ }
+
+ public boolean isExposeGC() {
+ return exposeGC;
+ }
+
+ public void setExposeGC(boolean exposeGC) {
+ if (!sealed) {
+ this.exposeGC = exposeGC;
+ }
+ }
+
+ public boolean isUseStrict() {
+ return useStrict;
+ }
+
+ public void setUseStrict(boolean useStrict) {
+ if (!sealed) {
+ this.useStrict = useStrict;
+ }
+ }
+
+ public boolean isAllowNativesSyntax() {
+ return allowNativesSyntax;
+ }
+
+ public void setAllowNativesSyntax(boolean allowNativesSyntax) {
+ if (!sealed) {
+ this.allowNativesSyntax = allowNativesSyntax;
+ }
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interop/V8Host.java b/src/main/java/com/caoccao/javet/interop/V8Host.java
new file mode 100644
index 000000000..6a4d86d2b
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/V8Host.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.interop;
+
+import com.caoccao.javet.exceptions.JavetException;
+import com.caoccao.javet.exceptions.JavetIOException;
+import com.caoccao.javet.exceptions.JavetOSNotSupportedException;
+import com.caoccao.javet.exceptions.JavetV8RuntimeLeakException;
+import com.caoccao.javet.interfaces.IJavetLogger;
+import com.caoccao.javet.utils.JavetDefaultLogger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public final class V8Host implements AutoCloseable {
+ private static final long INVALID_HANDLE = 0L;
+ private static final String FLAG_ALLOW_NATIVES_SYNTAX = "--allow-natives-syntax";
+ private static final String FLAG_EXPOSE_GC = "--expose_gc";
+ private static final String FLAG_TRACK_RETAINING_PATH = "--track-retaining-path";
+ private static final String FLAG_USE_STRICT = "--use_strict";
+ private static final String SPACE = " ";
+ private static V8Host instance = new V8Host();
+
+ private boolean closed;
+ private boolean libLoaded;
+ private boolean isolateCreated;
+ private ConcurrentHashMap v8RuntimeMap;
+ private JavetException lastException;
+ private V8Flags flags;
+ private IJavetLogger logger;
+
+ private V8Host() {
+ closed = true;
+ libLoaded = false;
+ lastException = null;
+ flags = new V8Flags();
+ logger = new JavetDefaultLogger(getClass().getName());
+ v8RuntimeMap = new ConcurrentHashMap<>();
+ try {
+ libLoaded = JavetLibLoader.load();
+ closed = false;
+ } catch (JavetOSNotSupportedException | JavetIOException e) {
+ logger.logError(e, "Failed to load Javet lib with error {0}.", e.getMessage());
+ lastException = e;
+ }
+ isolateCreated = false;
+ }
+
+ public static V8Host getInstance() {
+ return instance;
+ }
+
+ public V8Runtime createV8Runtime() {
+ return createV8Runtime(null);
+ }
+
+ public V8Flags getFlags() {
+ return flags;
+ }
+
+ public V8Runtime createV8Runtime(String globalName) {
+ return createV8Runtime(false, globalName);
+ }
+
+ public V8Runtime createV8Runtime(boolean pooled, String globalName) {
+ if (closed) {
+ return null;
+ }
+ final long handle = V8Native.createV8Runtime(globalName);
+ isolateCreated = true;
+ flags.seal();
+ V8Runtime v8Runtime = new V8Runtime(this, handle, pooled, globalName);
+ v8RuntimeMap.put(handle, v8Runtime);
+ return v8Runtime;
+ }
+
+ public void closeV8Runtime(V8Runtime v8Runtime) {
+ if (closed) {
+ return;
+ }
+ if (v8Runtime != null) {
+ final long handle = v8Runtime.getHandle();
+ if (handle > INVALID_HANDLE && v8RuntimeMap.containsKey(handle)) {
+ V8Native.closeV8Runtime(v8Runtime.getHandle());
+ v8RuntimeMap.remove(handle);
+ }
+ }
+ }
+
+ public int getV8RuntimeCount() {
+ return v8RuntimeMap.size();
+ }
+
+ public boolean isLibLoaded() {
+ return libLoaded;
+ }
+
+ public JavetException getLastException() {
+ return lastException;
+ }
+
+ public boolean isIsolateCreated() {
+ return isolateCreated;
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+
+ public boolean setFlags() {
+ if (!closed && libLoaded && !isolateCreated) {
+ List flags = new ArrayList<>();
+ if (this.flags.isAllowNativesSyntax()) {
+ flags.add(FLAG_ALLOW_NATIVES_SYNTAX);
+ }
+ if (this.flags.isExposeGC()) {
+ flags.add(FLAG_EXPOSE_GC);
+ }
+ if (this.flags.isUseStrict()) {
+ flags.add(FLAG_USE_STRICT);
+ }
+ if (this.flags.isTrackRetainingPath()) {
+ flags.add(FLAG_TRACK_RETAINING_PATH);
+ }
+ V8Native.setFlags(String.join(SPACE, flags));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void close() throws JavetException {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ final int v8RuntimeCount = getV8RuntimeCount();
+ if (v8RuntimeCount != 0) {
+ throw new JavetV8RuntimeLeakException(v8RuntimeCount);
+ }
+ }
+}
diff --git a/src/main/java/com/caoccao/javet/interop/V8Native.java b/src/main/java/com/caoccao/javet/interop/V8Native.java
new file mode 100644
index 000000000..ccc179f19
--- /dev/null
+++ b/src/main/java/com/caoccao/javet/interop/V8Native.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2021. caoccao.com Sam Cao
+ *
+ * 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.caoccao.javet.interop;
+
+/**
+ * The type V8 native is the pure interface that defines the JNI C++ implementation.
+ *