From 57210c8ed0ae06f1c9e69bb48dd621f355fa8068 Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Thu, 24 Jun 2021 14:58:58 +0800 Subject: [PATCH] Javet v0.9.2 (#49) * Upgraded Node.js to `v14.17.1` [(2021-06-15)](https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V14.md#14.17.1) * Updated `JavetObjectConverter` to handle anonymous functions more efficiently * Added `V8ValueBuiltInObject#assign` --- README.rst | 8 +- build.gradle.kts | 2 +- cpp/build.cmd | 2 +- cpp/build.sh | 2 +- cpp/jni/javet_resource_node.rc | 12 +- cpp/jni/javet_resource_v8.rc | 12 +- docs/development/build.rst | 2 +- docs/development/tools.rst | 2 +- docs/release_notes.rst | 7 + docs/tutorial/installation.rst | 6 +- pom.xml | 4 +- scripts/node/javet-rebuild/rebuild.cmd | 2 +- scripts/node/javet-rebuild/rebuild.sh | 2 +- scripts/python/change_javet_version.py | 2 +- .../javet/annotations/CheckReturnValue.java | 30 +- .../javet/annotations/V8RuntimeSetter.java | 62 +- .../caoccao/javet/enums/JSFunctionType.java | 98 +-- .../caoccao/javet/enums/JSRuntimeType.java | 2 +- .../com/caoccao/javet/enums/JSScopeType.java | 168 ++--- .../caoccao/javet/enums/JavetErrorType.java | 148 ++--- .../javet/enums/JavetPromiseRejectEvent.java | 108 ++-- .../caoccao/javet/exceptions/JavetError.java | 256 ++++---- .../IJavetPromiseRejectCallback.java | 80 +-- .../caoccao/javet/interop/IV8Convertible.java | 150 ++--- .../caoccao/javet/interop/JavetLibLoader.java | 2 +- .../javet/interop/V8FunctionCallback.java | 576 +++++++++--------- .../com/caoccao/javet/interop/V8Notifier.java | 126 ++-- .../com/caoccao/javet/interop/V8Runtime.java | 9 +- .../javet/interop/binding/BindingContext.java | 99 +++ .../interop/binding/MethodDescriptor.java | 63 ++ .../converters/JavetObjectConverter.java | 7 +- .../utils/JavetPromiseRejectCallback.java | 74 +-- .../javet/utils/SimpleFreeMarkerFormat.java | 228 +++---- .../com/caoccao/javet/utils/SimpleMap.java | 296 ++++----- .../values/reference/V8ValueGlobalObject.java | 12 +- .../javet/values/reference/V8ValueObject.java | 202 +++--- .../builtin/V8ValueBuiltInObject.java | 44 ++ .../javet/values/virtual/V8VirtualValue.java | 102 ++-- .../javet/exceptions/TestJavetError.java | 232 +++---- .../caoccao/javet/interop/TestV8Locker.java | 106 ++-- .../converters/TestJavetCustomConverter.java | 266 ++++---- .../converters/TestJavetObjectConverter.java | 509 ++++++++-------- .../TestJavetPrimitiveConverter.java | 174 +++--- .../interop/engine/TestJavetEngineGuard.java | 132 ++-- .../javet/interop/engine/TestPerformance.java | 474 +++++++------- .../MockAnnotationBasedCallbackReceiver.java | 390 ++++++------ .../javet/tutorial/TestInterception.java | 214 +++---- .../caoccao/javet/tutorial/cdt/CDTConfig.java | 112 ++-- .../javet/tutorial/cdt/CDTHttpServlet.java | 126 ++-- .../caoccao/javet/tutorial/cdt/CDTShell.java | 190 +++--- .../tutorial/cdt/CDTWebSocketAdapter.java | 204 +++---- .../caoccao/javet/tutorial/cdt/TestCDT.java | 70 +-- .../utils/TestSimpleFreeMarkerFormat.java | 146 ++--- .../javet/values/reference/TestV8Module.java | 448 +++++++------- .../javet/values/reference/TestV8Script.java | 94 +-- .../builtin/TestV8ValueBuiltInJson.java | 89 +-- .../builtin/TestV8ValueBuiltInObject.java | 44 ++ 57 files changed, 3666 insertions(+), 3361 deletions(-) create mode 100644 src/main/java/com/caoccao/javet/interop/binding/BindingContext.java create mode 100644 src/main/java/com/caoccao/javet/interop/binding/MethodDescriptor.java create mode 100644 src/main/java/com/caoccao/javet/values/reference/builtin/V8ValueBuiltInObject.java create mode 100644 src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInObject.java diff --git a/README.rst b/README.rst index 019e34185..98694655a 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ Major Features ============== * 🐧Linux + 🖥️Windows -* Node.js ``v14.17.0`` + V8 ``v9.1.269.28`` +* Node.js ``v14.17.1`` + V8 ``v9.1.269.28`` * Dynamic switch between Node.js and V8 * Exposure of the majority of V8 API in JVM * JS function interception @@ -40,7 +40,7 @@ Maven com.caoccao.javet javet - 0.9.1 + 0.9.2 Gradle Kotlin DSL @@ -48,14 +48,14 @@ Gradle Kotlin DSL .. code-block:: kotlin - implementation("com.caoccao.javet:javet:0.9.1") + implementation("com.caoccao.javet:javet:0.9.2") Gradle Groovy DSL ^^^^^^^^^^^^^^^^^ .. code-block:: groovy - implementation 'com.caoccao.javet:javet:0.9.1' + implementation 'com.caoccao.javet:javet:0.9.2' Hello Javet ----------- diff --git a/build.gradle.kts b/build.gradle.kts index b73ebf2bb..e60c359f7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ repositories { } group = "com.caoccao.javet" -version = "0.9.1" +version = "0.9.2" repositories { mavenCentral() diff --git a/cpp/build.cmd b/cpp/build.cmd index 6f15f946d..3b22d8abc 100644 --- a/cpp/build.cmd +++ b/cpp/build.cmd @@ -1,7 +1,7 @@ @echo off REM Usage for V8: build -DV8_DIR=C:\v8 REM Usage for Node: build -DNODE_DIR=C:\node -SET JAVET_VERSION=0.9.1 +SET JAVET_VERSION=0.9.2 rd /s/q build mkdir build cd build diff --git a/cpp/build.sh b/cpp/build.sh index bd7a17f96..8241e878d 100755 --- a/cpp/build.sh +++ b/cpp/build.sh @@ -2,7 +2,7 @@ # Usage for V8: build -DV8_DIR=~/v8 # Usage for Node: build -DNODE_DIR=~/node -JAVET_VERSION=0.9.1 +JAVET_VERSION=0.9.2 rm -rf build mkdir build cd build diff --git a/cpp/jni/javet_resource_node.rc b/cpp/jni/javet_resource_node.rc index a438f5b43..1ae33baf4 100644 --- a/cpp/jni/javet_resource_node.rc +++ b/cpp/jni/javet_resource_node.rc @@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,1,0 - PRODUCTVERSION 0,9,1,0 + FILEVERSION 0,9,2,0 + PRODUCTVERSION 0,9,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -79,12 +79,12 @@ BEGIN BEGIN VALUE "CompanyName", "caoccao.com" VALUE "FileDescription", "caoccao.com" - VALUE "FileVersion", "0.9.1.0" - VALUE "InternalName", "libjavet-node-windows-x86_64.v.0.9.1.dll" + VALUE "FileVersion", "0.9.2.0" + VALUE "InternalName", "libjavet-node-windows-x86_64.v.0.9.2.dll" VALUE "LegalCopyright", "Copyright (C) 2021" - VALUE "OriginalFilename", "libjavet-node-windows-x86_64.v.0.9.1.dll" + VALUE "OriginalFilename", "libjavet-node-windows-x86_64.v.0.9.2.dll" VALUE "ProductName", "Javet Windows" - VALUE "ProductVersion", "0.9.1.0" + VALUE "ProductVersion", "0.9.2.0" END END BLOCK "VarFileInfo" diff --git a/cpp/jni/javet_resource_v8.rc b/cpp/jni/javet_resource_v8.rc index 94ee1799e..6dd8ea0fd 100644 --- a/cpp/jni/javet_resource_v8.rc +++ b/cpp/jni/javet_resource_v8.rc @@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,1,0 - PRODUCTVERSION 0,9,1,0 + FILEVERSION 0,9,2,0 + PRODUCTVERSION 0,9,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -79,12 +79,12 @@ BEGIN BEGIN VALUE "CompanyName", "caoccao.com" VALUE "FileDescription", "caoccao.com" - VALUE "FileVersion", "0.9.1.0" - VALUE "InternalName", "libjavet-v8-windows-x86_64.v.0.9.1.dll" + VALUE "FileVersion", "0.9.2.0" + VALUE "InternalName", "libjavet-v8-windows-x86_64.v.0.9.2.dll" VALUE "LegalCopyright", "Copyright (C) 2021" - VALUE "OriginalFilename", "libjavet-v8-windows-x86_64.v.0.9.1.dll" + VALUE "OriginalFilename", "libjavet-v8-windows-x86_64.v.0.9.2.dll" VALUE "ProductName", "Javet Windows" - VALUE "ProductVersion", "0.9.1.0" + VALUE "ProductVersion", "0.9.2.0" END END BLOCK "VarFileInfo" diff --git a/docs/development/build.rst b/docs/development/build.rst index 51b965fdf..b28e5240c 100644 --- a/docs/development/build.rst +++ b/docs/development/build.rst @@ -26,7 +26,7 @@ Windows Environment Download Pre-built Node.js and V8 ================================= -I have prepared pre-built Linux and Windows version of Node.js ``v14.17.0`` and V8 ``v9.1.269.28``. Please download the zipped headers and binaries from this `drive `_ and unzip them to local folders respectively. +I have prepared pre-built Linux and Windows version of Node.js ``v14.17.1`` and V8 ``v9.1.269.28``. Please download the zipped headers and binaries from this `drive `_ and unzip them to local folders respectively. Build Javet JNI Library ======================= diff --git a/docs/development/tools.rst b/docs/development/tools.rst index d20e0caf3..3d75995f7 100644 --- a/docs/development/tools.rst +++ b/docs/development/tools.rst @@ -20,7 +20,7 @@ For now, Gradle v6.7 + Kotlin DSL constructs the build system. Node.js ================= -Node.js 14.17.0+ is supported. +Node.js 14.17.1+ is supported. Maven (Optional) ================ diff --git a/docs/release_notes.rst b/docs/release_notes.rst index 26902e997..ca161fb89 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -2,6 +2,13 @@ Release Notes ============= +0.9.2 +----- + +* Upgraded Node.js to ``v14.17.1`` `(2021-06-15) `_ +* Updated ``JavetObjectConverter`` to handle anonymous functions more efficiently +* Added ``V8ValueBuiltInObject#assign`` + 0.9.1 ----- diff --git a/docs/tutorial/installation.rst b/docs/tutorial/installation.rst index a32e2fb54..e5d148654 100644 --- a/docs/tutorial/installation.rst +++ b/docs/tutorial/installation.rst @@ -13,7 +13,7 @@ Maven com.caoccao.javet javet - 0.9.1 + 0.9.2 Gradle Kotlin DSL @@ -21,14 +21,14 @@ Gradle Kotlin DSL .. code-block:: kotlin - implementation("com.caoccao.javet:javet:0.9.1") + implementation("com.caoccao.javet:javet:0.9.2") Gradle Groovy DSL ----------------- .. code-block:: groovy - implementation 'com.caoccao.javet:javet:0.9.1' + implementation 'com.caoccao.javet:javet:0.9.2' OS Compatibility ================ diff --git a/pom.xml b/pom.xml index a77e5cb31..2235a5cdd 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.caoccao.javet javet - 0.9.1 + 0.9.2 javet Javet is Java + V8 (JAVa + V + EighT). It is a way of embedding V8 in Java. https://github.com/caoccao/Javet @@ -28,7 +28,7 @@ scm:git:git://github.com/caoccao/Javet.git scm:git:git@github.com:caoccao/caoccao.git https://github.com/caoccao/Javet - javet-0.9.1 + javet-0.9.2 diff --git a/scripts/node/javet-rebuild/rebuild.cmd b/scripts/node/javet-rebuild/rebuild.cmd index cf489ae0b..7547dde69 100644 --- a/scripts/node/javet-rebuild/rebuild.cmd +++ b/scripts/node/javet-rebuild/rebuild.cmd @@ -1,5 +1,5 @@ @echo off -SET NODE_LIB_FILE="..\..\..\..\..\..\build\libs\libjavet-node-windows-x86_64.v.0.9.1.lib" +SET NODE_LIB_FILE="..\..\..\..\..\..\build\libs\libjavet-node-windows-x86_64.v.0.9.2.lib" cd %NODE_MODULE_ROOT% call node-gyp clean call node-gyp configure --module_name=%NODE_MODULE_NAME% --module_path=%NODE_MODULE_PATH% --node_lib_file=%NODE_LIB_FILE% diff --git a/scripts/node/javet-rebuild/rebuild.sh b/scripts/node/javet-rebuild/rebuild.sh index 2d20f3753..503e0357f 100755 --- a/scripts/node/javet-rebuild/rebuild.sh +++ b/scripts/node/javet-rebuild/rebuild.sh @@ -1 +1 @@ -patchelf --add-needed libjavet-node-linux-x86_64.v.0.9.1.so ${NODE_MODULE_FILE} +patchelf --add-needed libjavet-node-linux-x86_64.v.0.9.2.so ${NODE_MODULE_FILE} diff --git a/scripts/python/change_javet_version.py b/scripts/python/change_javet_version.py index cdde6ce7c..128ea3701 100644 --- a/scripts/python/change_javet_version.py +++ b/scripts/python/change_javet_version.py @@ -109,7 +109,7 @@ def _update(self, relative_file_path: str, line_separator: str, *patterns: list) logging.info(' Updated.') def main(): - change_javet_version = ChangeJavetVersion('0.9.1') + change_javet_version = ChangeJavetVersion('0.9.2') change_javet_version.update() return 0 diff --git a/src/main/java/com/caoccao/javet/annotations/CheckReturnValue.java b/src/main/java/com/caoccao/javet/annotations/CheckReturnValue.java index 705266353..09840cc91 100644 --- a/src/main/java/com/caoccao/javet/annotations/CheckReturnValue.java +++ b/src/main/java/com/caoccao/javet/annotations/CheckReturnValue.java @@ -1,15 +1,15 @@ -package com.caoccao.javet.annotations; - -import java.lang.annotation.*; - -/** - * This annotation is for IDE to warn application developers to consume the return value. - * Memory leak may occur if the return value is not consumed. - * - * @since 0.8.10 - */ -@Documented -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.PACKAGE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface CheckReturnValue { -} +package com.caoccao.javet.annotations; + +import java.lang.annotation.*; + +/** + * This annotation is for IDE to warn application developers to consume the return value. + * Memory leak may occur if the return value is not consumed. + * + * @since 0.8.10 + */ +@Documented +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.PACKAGE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface CheckReturnValue { +} diff --git a/src/main/java/com/caoccao/javet/annotations/V8RuntimeSetter.java b/src/main/java/com/caoccao/javet/annotations/V8RuntimeSetter.java index 51d4c86f3..9a3314b78 100644 --- a/src/main/java/com/caoccao/javet/annotations/V8RuntimeSetter.java +++ b/src/main/java/com/caoccao/javet/annotations/V8RuntimeSetter.java @@ -1,31 +1,31 @@ -/* - * 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.annotations; - -import java.lang.annotation.*; - -/** - * The interface V8 runtime setter. - * - * @since 0.8.1 - */ -@Documented -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface V8RuntimeSetter { -} +/* + * 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.annotations; + +import java.lang.annotation.*; + +/** + * The interface V8 runtime setter. + * + * @since 0.8.1 + */ +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface V8RuntimeSetter { +} diff --git a/src/main/java/com/caoccao/javet/enums/JSFunctionType.java b/src/main/java/com/caoccao/javet/enums/JSFunctionType.java index 7338ae851..8d1c0aa79 100644 --- a/src/main/java/com/caoccao/javet/enums/JSFunctionType.java +++ b/src/main/java/com/caoccao/javet/enums/JSFunctionType.java @@ -1,49 +1,49 @@ -package com.caoccao.javet.enums; - -public enum JSFunctionType { - Native(0, "Native"), - API(1, "API"), - UserDefined(2, "UserDefined"), - Unknown(3, "Unknown"); - - private final int id; - private final String name; - - JSFunctionType(int id, String name) { - this.id = id; - this.name = name; - } - - public static JSFunctionType parse(int id) { - switch (id) { - case 0: - return Native; - case 1: - return API; - case 2: - return UserDefined; - default: - return Unknown; - } - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - public boolean isAPI() { - return this == API; - } - - public boolean isNative() { - return this == Native; - } - - public boolean isUserDefined() { - return this == UserDefined; - } -} +package com.caoccao.javet.enums; + +public enum JSFunctionType { + Native(0, "Native"), + API(1, "API"), + UserDefined(2, "UserDefined"), + Unknown(3, "Unknown"); + + private final int id; + private final String name; + + JSFunctionType(int id, String name) { + this.id = id; + this.name = name; + } + + public static JSFunctionType parse(int id) { + switch (id) { + case 0: + return Native; + case 1: + return API; + case 2: + return UserDefined; + default: + return Unknown; + } + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isAPI() { + return this == API; + } + + public boolean isNative() { + return this == Native; + } + + public boolean isUserDefined() { + return this == UserDefined; + } +} diff --git a/src/main/java/com/caoccao/javet/enums/JSRuntimeType.java b/src/main/java/com/caoccao/javet/enums/JSRuntimeType.java index 2be3d2e93..82ee573cc 100644 --- a/src/main/java/com/caoccao/javet/enums/JSRuntimeType.java +++ b/src/main/java/com/caoccao/javet/enums/JSRuntimeType.java @@ -18,7 +18,7 @@ package com.caoccao.javet.enums; public enum JSRuntimeType { - Node("node", "8.4.371.23-node.63"), + Node("node", "8.4.371.23-node.67"), V8("v8", "9.1.269.28"); private final String name; diff --git a/src/main/java/com/caoccao/javet/enums/JSScopeType.java b/src/main/java/com/caoccao/javet/enums/JSScopeType.java index ad120af69..551577621 100644 --- a/src/main/java/com/caoccao/javet/enums/JSScopeType.java +++ b/src/main/java/com/caoccao/javet/enums/JSScopeType.java @@ -1,84 +1,84 @@ -package com.caoccao.javet.enums; - -public enum JSScopeType { - Class(0, "Class"), - Eval(1, "Eval"), - Function(2, "Function"), - Module(3, "Module"), - Script(4, "Script"), - Catch(5, "Catch"), - Block(6, "Block"), - With(7, "With"), - Unknown(8, "Unknown"); - - private final int id; - private final String name; - - JSScopeType(int id, String name) { - this.id = id; - this.name = name; - } - - public static JSScopeType parse(int id) { - switch (id) { - case 0: - return Class; - case 1: - return Eval; - case 2: - return Function; - case 3: - return Module; - case 4: - return Script; - case 5: - return Catch; - case 6: - return Block; - case 7: - return With; - default: - return Unknown; - } - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - public boolean isBlock() { - return this == Block; - } - - public boolean isCatch() { - return this == Catch; - } - - public boolean isClass() { - return this == Class; - } - - public boolean isEval() { - return this == Eval; - } - - public boolean isFunction() { - return this == Function; - } - - public boolean isModule() { - return this == Module; - } - - public boolean isScript() { - return this == Script; - } - - public boolean isWith() { - return this == With; - } -} +package com.caoccao.javet.enums; + +public enum JSScopeType { + Class(0, "Class"), + Eval(1, "Eval"), + Function(2, "Function"), + Module(3, "Module"), + Script(4, "Script"), + Catch(5, "Catch"), + Block(6, "Block"), + With(7, "With"), + Unknown(8, "Unknown"); + + private final int id; + private final String name; + + JSScopeType(int id, String name) { + this.id = id; + this.name = name; + } + + public static JSScopeType parse(int id) { + switch (id) { + case 0: + return Class; + case 1: + return Eval; + case 2: + return Function; + case 3: + return Module; + case 4: + return Script; + case 5: + return Catch; + case 6: + return Block; + case 7: + return With; + default: + return Unknown; + } + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isBlock() { + return this == Block; + } + + public boolean isCatch() { + return this == Catch; + } + + public boolean isClass() { + return this == Class; + } + + public boolean isEval() { + return this == Eval; + } + + public boolean isFunction() { + return this == Function; + } + + public boolean isModule() { + return this == Module; + } + + public boolean isScript() { + return this == Script; + } + + public boolean isWith() { + return this == With; + } +} diff --git a/src/main/java/com/caoccao/javet/enums/JavetErrorType.java b/src/main/java/com/caoccao/javet/enums/JavetErrorType.java index 1bffc570e..a9aa067ea 100644 --- a/src/main/java/com/caoccao/javet/enums/JavetErrorType.java +++ b/src/main/java/com/caoccao/javet/enums/JavetErrorType.java @@ -1,74 +1,74 @@ -/* - * 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.enums; - -/** - * The enum Javet error type. - * - * @since 0.8.5 - */ -public enum JavetErrorType { - /** - * System javet error type. - * - * @since 0.8.5 - */ - System, - /** - * Compilation javet error type. - * - * @since 0.8.5 - */ - Compilation, - /** - * Execution javet error type. - * - * @since 0.8.5 - */ - Execution, - /** - * Callback javet error type. - * - * @since 0.8.5 - */ - Callback, - /** - * Converter javet error type. - * - * @since 0.8.5 - */ - Converter, - /** - * Module javet error type. - * - * @since 0.8.5 - */ - Module, - /** - * Lock javet error type. - * - * @since 0.8.5 - */ - Lock, - /** - * Runtime javet error type. - * - * @since 0.8.5 - */ - Runtime, -} +/* + * 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.enums; + +/** + * The enum Javet error type. + * + * @since 0.8.5 + */ +public enum JavetErrorType { + /** + * System javet error type. + * + * @since 0.8.5 + */ + System, + /** + * Compilation javet error type. + * + * @since 0.8.5 + */ + Compilation, + /** + * Execution javet error type. + * + * @since 0.8.5 + */ + Execution, + /** + * Callback javet error type. + * + * @since 0.8.5 + */ + Callback, + /** + * Converter javet error type. + * + * @since 0.8.5 + */ + Converter, + /** + * Module javet error type. + * + * @since 0.8.5 + */ + Module, + /** + * Lock javet error type. + * + * @since 0.8.5 + */ + Lock, + /** + * Runtime javet error type. + * + * @since 0.8.5 + */ + Runtime, +} diff --git a/src/main/java/com/caoccao/javet/enums/JavetPromiseRejectEvent.java b/src/main/java/com/caoccao/javet/enums/JavetPromiseRejectEvent.java index d1d271c92..7eafd4676 100644 --- a/src/main/java/com/caoccao/javet/enums/JavetPromiseRejectEvent.java +++ b/src/main/java/com/caoccao/javet/enums/JavetPromiseRejectEvent.java @@ -1,54 +1,54 @@ -/* - * 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.enums; - -public enum JavetPromiseRejectEvent { - PromiseRejectWithNoHandler(0, "PromiseRejectWithNoHandler"), - PromiseHandlerAddedAfterReject(1, "PromiseHandlerAddedAfterReject"), - PromiseResolveAfterResolved(2, "PromiseResolveAfterResolved"), - PromiseRejectAfterResolved(3, "PromiseRejectAfterResolved"); - - private static final JavetPromiseRejectEvent[] EVENTS = new JavetPromiseRejectEvent[]{ - PromiseRejectWithNoHandler, - PromiseHandlerAddedAfterReject, - PromiseResolveAfterResolved, - PromiseRejectAfterResolved}; - - private final int code; - private final String name; - - JavetPromiseRejectEvent(int code, String name) { - this.code = code; - this.name = name; - } - - public static JavetPromiseRejectEvent parse(int event) { - if (event >= 0 && event < EVENTS.length) { - return EVENTS[event]; - } - return null; - } - - public int getCode() { - return code; - } - - public String getName() { - return name; - } -} +/* + * 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.enums; + +public enum JavetPromiseRejectEvent { + PromiseRejectWithNoHandler(0, "PromiseRejectWithNoHandler"), + PromiseHandlerAddedAfterReject(1, "PromiseHandlerAddedAfterReject"), + PromiseResolveAfterResolved(2, "PromiseResolveAfterResolved"), + PromiseRejectAfterResolved(3, "PromiseRejectAfterResolved"); + + private static final JavetPromiseRejectEvent[] EVENTS = new JavetPromiseRejectEvent[]{ + PromiseRejectWithNoHandler, + PromiseHandlerAddedAfterReject, + PromiseResolveAfterResolved, + PromiseRejectAfterResolved}; + + private final int code; + private final String name; + + JavetPromiseRejectEvent(int code, String name) { + this.code = code; + this.name = name; + } + + public static JavetPromiseRejectEvent parse(int event) { + if (event >= 0 && event < EVENTS.length) { + return EVENTS[event]; + } + return null; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/caoccao/javet/exceptions/JavetError.java b/src/main/java/com/caoccao/javet/exceptions/JavetError.java index daa3d0d2e..0450c280f 100644 --- a/src/main/java/com/caoccao/javet/exceptions/JavetError.java +++ b/src/main/java/com/caoccao/javet/exceptions/JavetError.java @@ -1,128 +1,128 @@ -/* - * 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 com.caoccao.javet.enums.JavetErrorType; -import com.caoccao.javet.utils.SimpleFreeMarkerFormat; - -import java.util.Map; - -public class JavetError { - public static final String PARAMETER_EXPECTED_PARAMETER_TYPE = "expectedParameterType"; - public static final String PARAMETER_ACTUAL_PARAMETER_TYPE = "actualParameterType"; - public static final String PARAMETER_METHOD_NAME = "methodName"; - public static final String PARAMETER_EXPECTED_PARAMETER_SIZE = "expectedParameterSize"; - public static final String PARAMETER_ACTUAL_PARAMETER_SIZE = "actualParameterSize"; - - public static final String PARAMETER_RESOURCE_NAME = "resourceName"; - public static final String PARAMETER_SOURCE_LINE = "sourceLine"; - public static final String PARAMETER_LINE_NUMBER = "lineNumber"; - public static final String PARAMETER_START_COLUMN = "startColumn"; - public static final String PARAMETER_END_COLUMN = "endColumn"; - public static final String PARAMETER_START_POSITION = "startPosition"; - public static final String PARAMETER_END_POSITION = "endPosition"; - public static final String PARAMETER_MESSAGE = "message"; - - public static final String PARAMETER_CURRENT_THREAD_ID = "currentThreadId"; - public static final String PARAMETER_LOCKED_THREAD_ID = "lockedThreadId"; - - public static final String PARAMETER_OS = "OS"; - - public static final String PARAMETER_FEATURE = "feature"; - - public static final String PARAMETER_COUNT = "count"; - public static final String PARAMETER_CONTINUABLE = "continuable"; - public static final String PARAMETER_PATH = "path"; - public static final String PARAMETER_REASON = "reason"; - - public static final JavetError OSNotSupported = new JavetError( - 101, JavetErrorType.System, "OS ${OS} is not supported"); - public static final JavetError LibraryNotFound = new JavetError( - 102, JavetErrorType.System, "Javet library ${path} is not found"); - public static final JavetError LibraryNotLoaded = new JavetError( - 103, JavetErrorType.System, "Javet library is not loaded because ${reason}"); - public static final JavetError NotSupported = new JavetError( - 104, JavetErrorType.System, "${feature} is not supported"); - public static final JavetError FailedToReadPath = new JavetError( - 105, JavetErrorType.System, "Failed to read ${path}"); - - public static final JavetError CompilationFailure = new JavetError( - 201, JavetErrorType.Compilation, "${message}"); - - public static final JavetError ExecutionFailure = new JavetError( - 301, JavetErrorType.Execution, "${message}"); - public static final JavetError ExecutionTerminated = new JavetError( - 302, JavetErrorType.Execution, "Execution is terminated and continuable is ${continuable}"); - - public static final JavetError CallbackSignatureParameterSizeMismatch = new JavetError( - 401, JavetErrorType.Callback, "Callback signature mismatches: method name is ${methodName}, expected parameter size is ${expectedParameterSize}, actual parameter size is ${actualParameterSize}"); - public static final JavetError CallbackSignatureParameterTypeMismatch = new JavetError( - 402, JavetErrorType.Callback, "Callback signature mismatches: expected parameter type is ${expectedParameterType}, actual parameter type is ${actualParameterType}"); - public static final JavetError CallbackInjectionFailure = new JavetError( - 403, JavetErrorType.Callback, "Failed to inject runtime with error message ${message}"); - public static final JavetError CallbackRegistrationFailure = new JavetError( - 404, JavetErrorType.Callback, "Callback ${methodName} registration failed with error message ${message}"); - - public static final JavetError ConverterFailure = new JavetError( - 501, JavetErrorType.Converter, "Failed to convert values with error message ${message}"); - - public static final JavetError ModuleNameEmpty = new JavetError( - 601, JavetErrorType.Module, "Module name is empty"); - - public static final JavetError LockAcquisitionFailure = new JavetError( - 701, JavetErrorType.Lock, "Failed to acquire the lock"); - public static final JavetError LockReleaseFailure = new JavetError( - 702, JavetErrorType.Lock, "Failed to release the lock"); - public static final JavetError LockConflictThreadIdMismatch = new JavetError( - 703, JavetErrorType.Lock, "Runtime lock conflict is detected with locked thread ID ${lockedThreadID} and current thread ID ${currentThreadID}"); - - public static final JavetError RuntimeAlreadyClosed = new JavetError( - 801, JavetErrorType.Runtime, "Runtime is already closed"); - public static final JavetError RuntimeAlreadyRegistered = new JavetError( - 802, JavetErrorType.Runtime, "Runtime is already registered"); - public static final JavetError RuntimeNotRegistered = new JavetError( - 803, JavetErrorType.Runtime, "Runtime is not registered"); - public static final JavetError RuntimeLeakageDetected = new JavetError( - 804, JavetErrorType.Runtime, "${count} runtime(s) leakage is detected"); - - protected int code; - protected String format; - protected JavetErrorType type; - - JavetError(int code, JavetErrorType type, String format) { - this.code = code; - this.format = format; - this.type = type; - } - - public int getCode() { - return code; - } - - public String getFormat() { - return format; - } - - public String getMessage(Map parameters) { - return SimpleFreeMarkerFormat.format(format, parameters); - } - - public JavetErrorType getType() { - return type; - } -} +/* + * 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 com.caoccao.javet.enums.JavetErrorType; +import com.caoccao.javet.utils.SimpleFreeMarkerFormat; + +import java.util.Map; + +public class JavetError { + public static final String PARAMETER_EXPECTED_PARAMETER_TYPE = "expectedParameterType"; + public static final String PARAMETER_ACTUAL_PARAMETER_TYPE = "actualParameterType"; + public static final String PARAMETER_METHOD_NAME = "methodName"; + public static final String PARAMETER_EXPECTED_PARAMETER_SIZE = "expectedParameterSize"; + public static final String PARAMETER_ACTUAL_PARAMETER_SIZE = "actualParameterSize"; + + public static final String PARAMETER_RESOURCE_NAME = "resourceName"; + public static final String PARAMETER_SOURCE_LINE = "sourceLine"; + public static final String PARAMETER_LINE_NUMBER = "lineNumber"; + public static final String PARAMETER_START_COLUMN = "startColumn"; + public static final String PARAMETER_END_COLUMN = "endColumn"; + public static final String PARAMETER_START_POSITION = "startPosition"; + public static final String PARAMETER_END_POSITION = "endPosition"; + public static final String PARAMETER_MESSAGE = "message"; + + public static final String PARAMETER_CURRENT_THREAD_ID = "currentThreadId"; + public static final String PARAMETER_LOCKED_THREAD_ID = "lockedThreadId"; + + public static final String PARAMETER_OS = "OS"; + + public static final String PARAMETER_FEATURE = "feature"; + + public static final String PARAMETER_COUNT = "count"; + public static final String PARAMETER_CONTINUABLE = "continuable"; + public static final String PARAMETER_PATH = "path"; + public static final String PARAMETER_REASON = "reason"; + + public static final JavetError OSNotSupported = new JavetError( + 101, JavetErrorType.System, "OS ${OS} is not supported"); + public static final JavetError LibraryNotFound = new JavetError( + 102, JavetErrorType.System, "Javet library ${path} is not found"); + public static final JavetError LibraryNotLoaded = new JavetError( + 103, JavetErrorType.System, "Javet library is not loaded because ${reason}"); + public static final JavetError NotSupported = new JavetError( + 104, JavetErrorType.System, "${feature} is not supported"); + public static final JavetError FailedToReadPath = new JavetError( + 105, JavetErrorType.System, "Failed to read ${path}"); + + public static final JavetError CompilationFailure = new JavetError( + 201, JavetErrorType.Compilation, "${message}"); + + public static final JavetError ExecutionFailure = new JavetError( + 301, JavetErrorType.Execution, "${message}"); + public static final JavetError ExecutionTerminated = new JavetError( + 302, JavetErrorType.Execution, "Execution is terminated and continuable is ${continuable}"); + + public static final JavetError CallbackSignatureParameterSizeMismatch = new JavetError( + 401, JavetErrorType.Callback, "Callback signature mismatches: method name is ${methodName}, expected parameter size is ${expectedParameterSize}, actual parameter size is ${actualParameterSize}"); + public static final JavetError CallbackSignatureParameterTypeMismatch = new JavetError( + 402, JavetErrorType.Callback, "Callback signature mismatches: expected parameter type is ${expectedParameterType}, actual parameter type is ${actualParameterType}"); + public static final JavetError CallbackInjectionFailure = new JavetError( + 403, JavetErrorType.Callback, "Failed to inject runtime with error message ${message}"); + public static final JavetError CallbackRegistrationFailure = new JavetError( + 404, JavetErrorType.Callback, "Callback ${methodName} registration failed with error message ${message}"); + + public static final JavetError ConverterFailure = new JavetError( + 501, JavetErrorType.Converter, "Failed to convert values with error message ${message}"); + + public static final JavetError ModuleNameEmpty = new JavetError( + 601, JavetErrorType.Module, "Module name is empty"); + + public static final JavetError LockAcquisitionFailure = new JavetError( + 701, JavetErrorType.Lock, "Failed to acquire the lock"); + public static final JavetError LockReleaseFailure = new JavetError( + 702, JavetErrorType.Lock, "Failed to release the lock"); + public static final JavetError LockConflictThreadIdMismatch = new JavetError( + 703, JavetErrorType.Lock, "Runtime lock conflict is detected with locked thread ID ${lockedThreadID} and current thread ID ${currentThreadID}"); + + public static final JavetError RuntimeAlreadyClosed = new JavetError( + 801, JavetErrorType.Runtime, "Runtime is already closed"); + public static final JavetError RuntimeAlreadyRegistered = new JavetError( + 802, JavetErrorType.Runtime, "Runtime is already registered"); + public static final JavetError RuntimeNotRegistered = new JavetError( + 803, JavetErrorType.Runtime, "Runtime is not registered"); + public static final JavetError RuntimeLeakageDetected = new JavetError( + 804, JavetErrorType.Runtime, "${count} runtime(s) leakage is detected"); + + protected int code; + protected String format; + protected JavetErrorType type; + + JavetError(int code, JavetErrorType type, String format) { + this.code = code; + this.format = format; + this.type = type; + } + + public int getCode() { + return code; + } + + public String getFormat() { + return format; + } + + public String getMessage(Map parameters) { + return SimpleFreeMarkerFormat.format(format, parameters); + } + + public JavetErrorType getType() { + return type; + } +} diff --git a/src/main/java/com/caoccao/javet/interfaces/IJavetPromiseRejectCallback.java b/src/main/java/com/caoccao/javet/interfaces/IJavetPromiseRejectCallback.java index 598fdea89..c519d0601 100644 --- a/src/main/java/com/caoccao/javet/interfaces/IJavetPromiseRejectCallback.java +++ b/src/main/java/com/caoccao/javet/interfaces/IJavetPromiseRejectCallback.java @@ -1,40 +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.interfaces; - -import com.caoccao.javet.enums.JavetPromiseRejectEvent; -import com.caoccao.javet.values.V8Value; -import com.caoccao.javet.values.reference.V8ValuePromise; - -/** - * The interface Javet promise reject callback. - * - * @since 0.8.3 - */ -public interface IJavetPromiseRejectCallback { - - /** - * Callback. - * - * @param event the event - * @param promise the promise - * @param value the value - * @since 0.8.3 - */ - void callback(JavetPromiseRejectEvent event, V8ValuePromise promise, V8Value value); -} +/* + * 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.enums.JavetPromiseRejectEvent; +import com.caoccao.javet.values.V8Value; +import com.caoccao.javet.values.reference.V8ValuePromise; + +/** + * The interface Javet promise reject callback. + * + * @since 0.8.3 + */ +public interface IJavetPromiseRejectCallback { + + /** + * Callback. + * + * @param event the event + * @param promise the promise + * @param value the value + * @since 0.8.3 + */ + void callback(JavetPromiseRejectEvent event, V8ValuePromise promise, V8Value value); +} diff --git a/src/main/java/com/caoccao/javet/interop/IV8Convertible.java b/src/main/java/com/caoccao/javet/interop/IV8Convertible.java index fd583ad0d..cb28a70f4 100644 --- a/src/main/java/com/caoccao/javet/interop/IV8Convertible.java +++ b/src/main/java/com/caoccao/javet/interop/IV8Convertible.java @@ -1,75 +1,75 @@ -/* - * 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.annotations.CheckReturnValue; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.values.V8Value; - -/** - * The interface V8 convertible. - */ -public interface IV8Convertible { - /** - * Convert from V8 value to object. - * The caller is responsible for closing the V8 value. - * - * @param the type parameter - * @param the type parameter - * @param v8Value the V8 value - * @return the object - * @throws JavetException the javet exception - */ - T toObject(V v8Value) throws JavetException; - - /** - * Convert from V8 value to object. - * The V8 value is closed automatically if autoClose is set to true. - * - * @param the type parameter - * @param the type parameter - * @param v8Value the V8 value - * @param autoClose the auto close - * @return the t - * @throws JavetException the javet exception - */ - default T toObject(V v8Value, boolean autoClose) throws JavetException { - if (autoClose) { - try { - return toObject(v8Value); - } finally { - JavetResourceUtils.safeClose(v8Value); - } - } else { - return toObject(v8Value); - } - } - - /** - * Convert object to V8 value. - * - * @param the type parameter - * @param the type parameter - * @param object the object - * @return the V8 value - * @throws JavetException the javet exception - */ - @CheckReturnValue - V toV8Value(T object) throws JavetException; -} +/* + * 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.annotations.CheckReturnValue; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.utils.JavetResourceUtils; +import com.caoccao.javet.values.V8Value; + +/** + * The interface V8 convertible. + */ +public interface IV8Convertible { + /** + * Convert from V8 value to object. + * The caller is responsible for closing the V8 value. + * + * @param the type parameter + * @param the type parameter + * @param v8Value the V8 value + * @return the object + * @throws JavetException the javet exception + */ + T toObject(V v8Value) throws JavetException; + + /** + * Convert from V8 value to object. + * The V8 value is closed automatically if autoClose is set to true. + * + * @param the type parameter + * @param the type parameter + * @param v8Value the V8 value + * @param autoClose the auto close + * @return the t + * @throws JavetException the javet exception + */ + default T toObject(V v8Value, boolean autoClose) throws JavetException { + if (autoClose) { + try { + return toObject(v8Value); + } finally { + JavetResourceUtils.safeClose(v8Value); + } + } else { + return toObject(v8Value); + } + } + + /** + * Convert object to V8 value. + * + * @param the type parameter + * @param the type parameter + * @param object the object + * @return the V8 value + * @throws JavetException the javet exception + */ + @CheckReturnValue + V toV8Value(T object) throws JavetException; +} diff --git a/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java b/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java index c772ee439..c674a750a 100644 --- a/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java +++ b/src/main/java/com/caoccao/javet/interop/JavetLibLoader.java @@ -30,7 +30,7 @@ import java.util.Objects; public final class JavetLibLoader { - static final String LIB_VERSION = "0.9.1"; + static final String LIB_VERSION = "0.9.2"; private static final int BUFFER_LENGTH = 4096; private static final String CHMOD = "chmod"; private static final String LIB_FILE_EXTENSION_LINUX = "so"; diff --git a/src/main/java/com/caoccao/javet/interop/V8FunctionCallback.java b/src/main/java/com/caoccao/javet/interop/V8FunctionCallback.java index a3fdb372a..f5367c340 100644 --- a/src/main/java/com/caoccao/javet/interop/V8FunctionCallback.java +++ b/src/main/java/com/caoccao/javet/interop/V8FunctionCallback.java @@ -1,288 +1,288 @@ -/* - * 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.JavetError; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interop.converters.IJavetConverter; -import com.caoccao.javet.utils.JavetCallbackContext; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.utils.SimpleMap; -import com.caoccao.javet.values.V8Value; -import com.caoccao.javet.values.reference.V8ValueArray; - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -public final class V8FunctionCallback { - - private static Object convert(IJavetConverter converter, Class expectedClass, V8Value v8Value) - throws JavetException { - if (v8Value == null) { - // This check is for null safety. - if (expectedClass.isPrimitive()) { - /* - * The following test is based on statistical analysis - * so that the performance can be maximized. - */ - if (expectedClass == int.class) { - return converter.getDefaultInt(); - } else if (expectedClass == boolean.class) { - return converter.getDefaultBoolean(); - } else if (expectedClass == double.class) { - return converter.getDefaultDouble(); - } else if (expectedClass == float.class) { - return converter.getDefaultFloat(); - } else if (expectedClass == long.class) { - return converter.getDefaultLong(); - } else if (expectedClass == short.class) { - return converter.getDefaultShort(); - } else if (expectedClass == byte.class) { - return converter.getDefaultByte(); - } else if (expectedClass == char.class) { - return converter.getDefaultChar(); - } - } - } else if (expectedClass.isAssignableFrom(v8Value.getClass())) { - // Skip assignable - } else { - Object convertedObject = converter.toObject(v8Value); - if (convertedObject == null) { - return convert(converter, expectedClass, null); - } else { - Class convertedObjectClass = convertedObject.getClass(); - if (expectedClass.isAssignableFrom(convertedObjectClass)) { - return convertedObject; - } else if (expectedClass.isPrimitive()) { - /* - * The following test is based on statistical analysis - * so that the performance can be maximized. - */ - if (expectedClass == int.class) { - if (convertedObjectClass == Integer.class) { - //noinspection UnnecessaryUnboxing - return ((Integer) convertedObject).intValue(); - } else if (convertedObjectClass == Long.class) { - return ((Long) convertedObject).intValue(); - } else if (convertedObjectClass == Short.class) { - return ((Short) convertedObject).intValue(); - } else if (convertedObjectClass == Byte.class) { - return ((Byte) convertedObject).intValue(); - } - } else if (expectedClass == boolean.class && convertedObjectClass == Boolean.class) { - //noinspection UnnecessaryUnboxing - return ((Boolean) convertedObject).booleanValue(); - } else if (expectedClass == double.class) { - if (convertedObjectClass == Double.class) { - //noinspection UnnecessaryUnboxing - return ((Double) convertedObject).doubleValue(); - } else if (convertedObjectClass == Float.class) { - return ((Float) convertedObject).doubleValue(); - } else if (convertedObjectClass == Integer.class) { - return ((Integer) convertedObject).doubleValue(); - } else if (convertedObjectClass == Long.class) { - return ((Long) convertedObject).doubleValue(); - } else if (convertedObjectClass == Short.class) { - return ((Short) convertedObject).doubleValue(); - } else if (convertedObjectClass == Byte.class) { - return ((Byte) convertedObject).doubleValue(); - } - } else if (expectedClass == float.class) { - if (convertedObjectClass == Double.class) { - return ((Double) convertedObject).floatValue(); - } else if (convertedObjectClass == Float.class) { - //noinspection UnnecessaryUnboxing - return ((Float) convertedObject).floatValue(); - } else if (convertedObjectClass == Integer.class) { - return ((Integer) convertedObject).floatValue(); - } else if (convertedObjectClass == Long.class) { - return ((Long) convertedObject).floatValue(); - } else if (convertedObjectClass == Short.class) { - return ((Short) convertedObject).floatValue(); - } else if (convertedObjectClass == Byte.class) { - return ((Byte) convertedObject).floatValue(); - } - } else if (expectedClass == long.class) { - if (convertedObjectClass == Long.class) { - //noinspection UnnecessaryUnboxing - return ((Long) convertedObject).longValue(); - } else if (convertedObjectClass == Integer.class) { - return ((Integer) convertedObject).longValue(); - } else if (convertedObjectClass == Short.class) { - return ((Short) convertedObject).longValue(); - } else if (convertedObjectClass == Byte.class) { - return ((Byte) convertedObject).longValue(); - } - } else if (expectedClass == short.class) { - if (convertedObjectClass == Short.class) { - //noinspection UnnecessaryUnboxing - return ((Short) convertedObject).shortValue(); - } else if (convertedObjectClass == Integer.class) { - return ((Integer) convertedObject).shortValue(); - } else if (convertedObjectClass == Long.class) { - return ((Long) convertedObject).shortValue(); - } else if (convertedObjectClass == Byte.class) { - return ((Byte) convertedObject).shortValue(); - } - } else if (expectedClass == byte.class) { - if (convertedObjectClass == Byte.class) { - //noinspection UnnecessaryUnboxing - return ((Byte) convertedObject).byteValue(); - } else if (convertedObjectClass == Integer.class) { - return ((Integer) convertedObject).byteValue(); - } else if (convertedObjectClass == Long.class) { - return ((Long) convertedObject).byteValue(); - } else if (convertedObjectClass == Short.class) { - return ((Short) convertedObject).byteValue(); - } - } else if (expectedClass == char.class) { - if (convertedObjectClass == Character.class) { - //noinspection UnnecessaryUnboxing - return ((Character) convertedObject).charValue(); - } else if (convertedObjectClass == String.class) { - String convertedString = (String) convertedObject; - return convertedString.length() > 0 ? convertedString.charAt(0) : converter.getDefaultChar(); - } - } - } - } - throw new JavetException( - JavetError.CallbackSignatureParameterTypeMismatch, - SimpleMap.of( - JavetError.PARAMETER_EXPECTED_PARAMETER_TYPE, expectedClass, - JavetError.PARAMETER_ACTUAL_PARAMETER_TYPE, convertedObject.getClass())); - } - return v8Value; - } - - public static V8Value receiveCallback( - V8Runtime v8Runtime, - JavetCallbackContext javetCallbackContext, - V8Value thisObject, - V8ValueArray args) throws Throwable { - if (javetCallbackContext != null) { - List values = new ArrayList<>(); - Object resultObject = null; - try { - v8Runtime.decorateV8Values(thisObject, args); - /* - * Converter is the key to automatic type conversion. - * If the call doesn't want automatic type conversion, - * it's better to inject V8Runtime via @V8RuntimeSetter - * to the receiver so that the receiver can create reference V8Value. - */ - IJavetConverter converter = v8Runtime.getConverter(); - /* - * Javet doesn't check whether callback method is static or not. - * If the callback receiver is null, that's a static method. - */ - Method method = javetCallbackContext.getCallbackMethod(); - Object callbackReceiver = javetCallbackContext.getCallbackReceiver(); - if (javetCallbackContext.isThisObjectRequired()) { - values.add(thisObject); - } - if (args != null) { - final int length = args.getLength(); - for (int i = 0; i < length; ++i) { - values.add(args.get(i)); - } - } - if (values.isEmpty()) { - if (method.isVarArgs()) { - Class[] parameterTypes = method.getParameterTypes(); - Class parameterClass = parameterTypes[parameterTypes.length - 1]; - Object varObject = Array.newInstance(parameterClass.getComponentType(), 0); - resultObject = method.invoke(callbackReceiver, varObject); - } else { - resultObject = method.invoke(callbackReceiver); - } - } else { - final int length = values.size(); - List objectValues = new ArrayList<>(); - Class[] parameterTypes = method.getParameterTypes(); - if (method.isVarArgs()) { - for (int i = 0; i < parameterTypes.length; ++i) { - Class parameterClass = parameterTypes[i]; - if (parameterClass.isArray() && i == parameterTypes.length - 1) { - // VarArgs is special. It requires special API to manipulate the array. - Class componentType = parameterClass.getComponentType(); - Object varObject = Array.newInstance(componentType, length - i); - for (int j = i; j < length; ++j) { - Array.set(varObject, j - i, - convert(converter, componentType, (V8Value) values.get(j))); - } - objectValues.add(varObject); - } else { - objectValues.add(convert(converter, parameterClass, (V8Value) values.get(i))); - } - } - } else { - if (method.getParameterCount() != length) { - throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, - SimpleMap.of( - JavetError.PARAMETER_METHOD_NAME, method.getName(), - JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, length, - JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); - } - for (int i = 0; i < parameterTypes.length; ++i) { - objectValues.add(convert(converter, parameterTypes[i], (V8Value) values.get(i))); - } - } - resultObject = method.invoke(callbackReceiver, objectValues.toArray()); - } - if (javetCallbackContext.isReturnResult()) { - if (resultObject instanceof V8Value) { - v8Runtime.decorateV8Value((V8Value) resultObject); - } else { - resultObject = v8Runtime.toV8Value(resultObject); - } - // The lifecycle of the result is handed over to JNI native implementation. - // So, close() or setWeak() must not be called. - return (V8Value) resultObject; - } else { - JavetResourceUtils.safeClose(resultObject); - } - } catch (Throwable t) { - if (t instanceof InvocationTargetException) { - throw t.getCause(); - } else { - throw t; - } - } finally { - // Result object must be excluded because it will be closed in JNI. - if (!javetCallbackContext.isThisObjectRequired()) { - if (thisObject != resultObject) { - JavetResourceUtils.safeClose(thisObject); - } - } - if (args != resultObject) { - JavetResourceUtils.safeClose(args); - } - for (Object value : values) { - if (value != resultObject) { - JavetResourceUtils.safeClose(value); - } - } - } - } - return v8Runtime.createV8ValueUndefined(); - } -} +/* + * 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.JavetError; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interop.converters.IJavetConverter; +import com.caoccao.javet.utils.JavetCallbackContext; +import com.caoccao.javet.utils.JavetResourceUtils; +import com.caoccao.javet.utils.SimpleMap; +import com.caoccao.javet.values.V8Value; +import com.caoccao.javet.values.reference.V8ValueArray; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public final class V8FunctionCallback { + + private static Object convert(IJavetConverter converter, Class expectedClass, V8Value v8Value) + throws JavetException { + if (v8Value == null) { + // This check is for null safety. + if (expectedClass.isPrimitive()) { + /* + * The following test is based on statistical analysis + * so that the performance can be maximized. + */ + if (expectedClass == int.class) { + return converter.getDefaultInt(); + } else if (expectedClass == boolean.class) { + return converter.getDefaultBoolean(); + } else if (expectedClass == double.class) { + return converter.getDefaultDouble(); + } else if (expectedClass == float.class) { + return converter.getDefaultFloat(); + } else if (expectedClass == long.class) { + return converter.getDefaultLong(); + } else if (expectedClass == short.class) { + return converter.getDefaultShort(); + } else if (expectedClass == byte.class) { + return converter.getDefaultByte(); + } else if (expectedClass == char.class) { + return converter.getDefaultChar(); + } + } + } else if (expectedClass.isAssignableFrom(v8Value.getClass())) { + // Skip assignable + } else { + Object convertedObject = converter.toObject(v8Value); + if (convertedObject == null) { + return convert(converter, expectedClass, null); + } else { + Class convertedObjectClass = convertedObject.getClass(); + if (expectedClass.isAssignableFrom(convertedObjectClass)) { + return convertedObject; + } else if (expectedClass.isPrimitive()) { + /* + * The following test is based on statistical analysis + * so that the performance can be maximized. + */ + if (expectedClass == int.class) { + if (convertedObjectClass == Integer.class) { + //noinspection UnnecessaryUnboxing + return ((Integer) convertedObject).intValue(); + } else if (convertedObjectClass == Long.class) { + return ((Long) convertedObject).intValue(); + } else if (convertedObjectClass == Short.class) { + return ((Short) convertedObject).intValue(); + } else if (convertedObjectClass == Byte.class) { + return ((Byte) convertedObject).intValue(); + } + } else if (expectedClass == boolean.class && convertedObjectClass == Boolean.class) { + //noinspection UnnecessaryUnboxing + return ((Boolean) convertedObject).booleanValue(); + } else if (expectedClass == double.class) { + if (convertedObjectClass == Double.class) { + //noinspection UnnecessaryUnboxing + return ((Double) convertedObject).doubleValue(); + } else if (convertedObjectClass == Float.class) { + return ((Float) convertedObject).doubleValue(); + } else if (convertedObjectClass == Integer.class) { + return ((Integer) convertedObject).doubleValue(); + } else if (convertedObjectClass == Long.class) { + return ((Long) convertedObject).doubleValue(); + } else if (convertedObjectClass == Short.class) { + return ((Short) convertedObject).doubleValue(); + } else if (convertedObjectClass == Byte.class) { + return ((Byte) convertedObject).doubleValue(); + } + } else if (expectedClass == float.class) { + if (convertedObjectClass == Double.class) { + return ((Double) convertedObject).floatValue(); + } else if (convertedObjectClass == Float.class) { + //noinspection UnnecessaryUnboxing + return ((Float) convertedObject).floatValue(); + } else if (convertedObjectClass == Integer.class) { + return ((Integer) convertedObject).floatValue(); + } else if (convertedObjectClass == Long.class) { + return ((Long) convertedObject).floatValue(); + } else if (convertedObjectClass == Short.class) { + return ((Short) convertedObject).floatValue(); + } else if (convertedObjectClass == Byte.class) { + return ((Byte) convertedObject).floatValue(); + } + } else if (expectedClass == long.class) { + if (convertedObjectClass == Long.class) { + //noinspection UnnecessaryUnboxing + return ((Long) convertedObject).longValue(); + } else if (convertedObjectClass == Integer.class) { + return ((Integer) convertedObject).longValue(); + } else if (convertedObjectClass == Short.class) { + return ((Short) convertedObject).longValue(); + } else if (convertedObjectClass == Byte.class) { + return ((Byte) convertedObject).longValue(); + } + } else if (expectedClass == short.class) { + if (convertedObjectClass == Short.class) { + //noinspection UnnecessaryUnboxing + return ((Short) convertedObject).shortValue(); + } else if (convertedObjectClass == Integer.class) { + return ((Integer) convertedObject).shortValue(); + } else if (convertedObjectClass == Long.class) { + return ((Long) convertedObject).shortValue(); + } else if (convertedObjectClass == Byte.class) { + return ((Byte) convertedObject).shortValue(); + } + } else if (expectedClass == byte.class) { + if (convertedObjectClass == Byte.class) { + //noinspection UnnecessaryUnboxing + return ((Byte) convertedObject).byteValue(); + } else if (convertedObjectClass == Integer.class) { + return ((Integer) convertedObject).byteValue(); + } else if (convertedObjectClass == Long.class) { + return ((Long) convertedObject).byteValue(); + } else if (convertedObjectClass == Short.class) { + return ((Short) convertedObject).byteValue(); + } + } else if (expectedClass == char.class) { + if (convertedObjectClass == Character.class) { + //noinspection UnnecessaryUnboxing + return ((Character) convertedObject).charValue(); + } else if (convertedObjectClass == String.class) { + String convertedString = (String) convertedObject; + return convertedString.length() > 0 ? convertedString.charAt(0) : converter.getDefaultChar(); + } + } + } + } + throw new JavetException( + JavetError.CallbackSignatureParameterTypeMismatch, + SimpleMap.of( + JavetError.PARAMETER_EXPECTED_PARAMETER_TYPE, expectedClass, + JavetError.PARAMETER_ACTUAL_PARAMETER_TYPE, convertedObject.getClass())); + } + return v8Value; + } + + public static V8Value receiveCallback( + V8Runtime v8Runtime, + JavetCallbackContext javetCallbackContext, + V8Value thisObject, + V8ValueArray args) throws Throwable { + if (javetCallbackContext != null) { + List values = new ArrayList<>(); + Object resultObject = null; + try { + v8Runtime.decorateV8Values(thisObject, args); + /* + * Converter is the key to automatic type conversion. + * If the call doesn't want automatic type conversion, + * it's better to inject V8Runtime via @V8RuntimeSetter + * to the receiver so that the receiver can create reference V8Value. + */ + IJavetConverter converter = v8Runtime.getConverter(); + /* + * Javet doesn't check whether callback method is static or not. + * If the callback receiver is null, that's a static method. + */ + Method method = javetCallbackContext.getCallbackMethod(); + Object callbackReceiver = javetCallbackContext.getCallbackReceiver(); + if (javetCallbackContext.isThisObjectRequired()) { + values.add(thisObject); + } + if (args != null) { + final int length = args.getLength(); + for (int i = 0; i < length; ++i) { + values.add(args.get(i)); + } + } + if (values.isEmpty()) { + if (method.isVarArgs()) { + Class[] parameterTypes = method.getParameterTypes(); + Class parameterClass = parameterTypes[parameterTypes.length - 1]; + Object varObject = Array.newInstance(parameterClass.getComponentType(), 0); + resultObject = method.invoke(callbackReceiver, varObject); + } else { + resultObject = method.invoke(callbackReceiver); + } + } else { + final int length = values.size(); + List objectValues = new ArrayList<>(); + Class[] parameterTypes = method.getParameterTypes(); + if (method.isVarArgs()) { + for (int i = 0; i < parameterTypes.length; ++i) { + Class parameterClass = parameterTypes[i]; + if (parameterClass.isArray() && i == parameterTypes.length - 1) { + // VarArgs is special. It requires special API to manipulate the array. + Class componentType = parameterClass.getComponentType(); + Object varObject = Array.newInstance(componentType, length - i); + for (int j = i; j < length; ++j) { + Array.set(varObject, j - i, + convert(converter, componentType, (V8Value) values.get(j))); + } + objectValues.add(varObject); + } else { + objectValues.add(convert(converter, parameterClass, (V8Value) values.get(i))); + } + } + } else { + if (method.getParameterCount() != length) { + throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, + SimpleMap.of( + JavetError.PARAMETER_METHOD_NAME, method.getName(), + JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, length, + JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); + } + for (int i = 0; i < parameterTypes.length; ++i) { + objectValues.add(convert(converter, parameterTypes[i], (V8Value) values.get(i))); + } + } + resultObject = method.invoke(callbackReceiver, objectValues.toArray()); + } + if (javetCallbackContext.isReturnResult()) { + if (resultObject instanceof V8Value) { + v8Runtime.decorateV8Value((V8Value) resultObject); + } else { + resultObject = v8Runtime.toV8Value(resultObject); + } + // The lifecycle of the result is handed over to JNI native implementation. + // So, close() or setWeak() must not be called. + return (V8Value) resultObject; + } else { + JavetResourceUtils.safeClose(resultObject); + } + } catch (Throwable t) { + if (t instanceof InvocationTargetException) { + throw t.getCause(); + } else { + throw t; + } + } finally { + // Result object must be excluded because it will be closed in JNI. + if (!javetCallbackContext.isThisObjectRequired()) { + if (thisObject != resultObject) { + JavetResourceUtils.safeClose(thisObject); + } + } + if (args != resultObject) { + JavetResourceUtils.safeClose(args); + } + for (Object value : values) { + if (value != resultObject) { + JavetResourceUtils.safeClose(value); + } + } + } + } + return v8Runtime.createV8ValueUndefined(); + } +} diff --git a/src/main/java/com/caoccao/javet/interop/V8Notifier.java b/src/main/java/com/caoccao/javet/interop/V8Notifier.java index 8dc097a09..3f542c441 100644 --- a/src/main/java/com/caoccao/javet/interop/V8Notifier.java +++ b/src/main/java/com/caoccao/javet/interop/V8Notifier.java @@ -1,63 +1,63 @@ -/* - * 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 javax.management.ListenerNotFoundException; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryNotificationInfo; -import java.util.concurrent.ConcurrentHashMap; - -public final class V8Notifier implements NotificationListener { - private final ConcurrentHashMap v8RuntimeMap; - - public V8Notifier(ConcurrentHashMap v8RuntimeMap) { - this.v8RuntimeMap = v8RuntimeMap; - } - - @Override - public void handleNotification(Notification notification, Object handback) { - String notificationType = notification.getType(); - if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notificationType) - || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(notificationType)) { - // This is thread-safe and async operation. - for (V8Runtime v8Runtime : v8RuntimeMap.values()) { - v8Runtime.setGCScheduled(true); - } - } - } - - public void registerListeners() { - NotificationEmitter notificationEmitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean(); - try { - notificationEmitter.removeNotificationListener(this, null, null); - } catch (ListenerNotFoundException ignored) { - } - notificationEmitter.addNotificationListener(this, null, null); - } - - public void unregisterListener() { - try { - NotificationEmitter notificationEmitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean(); - notificationEmitter.removeNotificationListener(this, null, null); - } catch (ListenerNotFoundException ignored) { - } - } -} +/* + * 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 javax.management.ListenerNotFoundException; +import javax.management.Notification; +import javax.management.NotificationEmitter; +import javax.management.NotificationListener; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryNotificationInfo; +import java.util.concurrent.ConcurrentHashMap; + +public final class V8Notifier implements NotificationListener { + private final ConcurrentHashMap v8RuntimeMap; + + public V8Notifier(ConcurrentHashMap v8RuntimeMap) { + this.v8RuntimeMap = v8RuntimeMap; + } + + @Override + public void handleNotification(Notification notification, Object handback) { + String notificationType = notification.getType(); + if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notificationType) + || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(notificationType)) { + // This is thread-safe and async operation. + for (V8Runtime v8Runtime : v8RuntimeMap.values()) { + v8Runtime.setGCScheduled(true); + } + } + } + + public void registerListeners() { + NotificationEmitter notificationEmitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean(); + try { + notificationEmitter.removeNotificationListener(this, null, null); + } catch (ListenerNotFoundException ignored) { + } + notificationEmitter.addNotificationListener(this, null, null); + } + + public void unregisterListener() { + try { + NotificationEmitter notificationEmitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean(); + notificationEmitter.removeNotificationListener(this, null, null); + } catch (ListenerNotFoundException ignored) { + } + } +} diff --git a/src/main/java/com/caoccao/javet/interop/V8Runtime.java b/src/main/java/com/caoccao/javet/interop/V8Runtime.java index 8bd71b9c3..125546ff6 100644 --- a/src/main/java/com/caoccao/javet/interop/V8Runtime.java +++ b/src/main/java/com/caoccao/javet/interop/V8Runtime.java @@ -23,6 +23,7 @@ import com.caoccao.javet.interfaces.IJavetClosable; import com.caoccao.javet.interfaces.IJavetLogger; import com.caoccao.javet.interfaces.IJavetPromiseRejectCallback; +import com.caoccao.javet.interop.binding.BindingContext; import com.caoccao.javet.interop.converters.IJavetConverter; import com.caoccao.javet.interop.converters.JavetObjectConverter; import com.caoccao.javet.interop.executors.IV8Executor; @@ -53,13 +54,12 @@ public class V8Runtime implements IJavetClosable, IV8Creatable, IV8Convertible { protected static final int V8_VALUE_BOOLEAN_TRUE_INDEX = 1; protected static final int V8_VALUE_NUMBER_LOWER_BOUND = -128; // Inclusive protected static final int V8_VALUE_NUMBER_UPPER_BOUND = 128; // Exclusive - + protected WeakHashMap, BindingContext> bindingContextWeakHashMap; protected V8ValueBoolean[] cachedV8ValueBooleans; protected V8ValueInteger[] cachedV8ValueIntegers; protected V8ValueLong[] cachedV8ValueLongs; protected V8ValueNull cachedV8ValueNull; protected V8ValueUndefined cachedV8ValueUndefined; - /* * V8 may not make final callback when V8 context is being recycled. * That may results in memory leak. @@ -81,6 +81,7 @@ public class V8Runtime implements IJavetClosable, IV8Creatable, IV8Convertible { V8Runtime(V8Host v8Host, long handle, boolean pooled, IV8Native v8Native, String globalName) { assert handle != 0; + bindingContextWeakHashMap = new WeakHashMap<>(); callbackContextMap = new TreeMap<>(); converter = DEFAULT_CONVERTER; gcScheduled = false; @@ -334,6 +335,10 @@ public T get( handle, iV8ValueObject.getHandle(), iV8ValueObject.getType().getId(), key)); } + public WeakHashMap, BindingContext> getBindingContextWeakHashMap() { + return bindingContextWeakHashMap; + } + public int getCallbackContextCount() { return callbackContextMap.size(); } diff --git a/src/main/java/com/caoccao/javet/interop/binding/BindingContext.java b/src/main/java/com/caoccao/javet/interop/binding/BindingContext.java new file mode 100644 index 000000000..995f086e5 --- /dev/null +++ b/src/main/java/com/caoccao/javet/interop/binding/BindingContext.java @@ -0,0 +1,99 @@ +/* + * 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.binding; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * The type Binding context. + */ +public class BindingContext { + /** + * The Function map. + */ + protected Map functionMap; + /** + * The Property getter map. + */ + protected Map propertyGetterMap; + /** + * The Property setter map. + */ + protected Map propertySetterMap; + /** + * The V8 runtime setter. + */ + protected Method v8RuntimeSetter; + + /** + * Instantiates a new Binding context. + */ + public BindingContext() { + functionMap = new HashMap<>(); + propertyGetterMap = new HashMap<>(); + propertySetterMap = new HashMap<>(); + v8RuntimeSetter = null; + } + + /** + * Gets function map. + * + * @return the function map + */ + public Map getFunctionMap() { + return functionMap; + } + + /** + * Gets property getter map. + * + * @return the property getter map + */ + public Map getPropertyGetterMap() { + return propertyGetterMap; + } + + /** + * Gets property setter map. + * + * @return the property setter map + */ + public Map getPropertySetterMap() { + return propertySetterMap; + } + + /** + * Gets V8 runtime setter. + * + * @return the V8 runtime setter + */ + public Method getV8RuntimeSetter() { + return v8RuntimeSetter; + } + + /** + * Sets V8 runtime setter. + * + * @param v8RuntimeSetter the V8 runtime setter + */ + public void setV8RuntimeSetter(Method v8RuntimeSetter) { + this.v8RuntimeSetter = v8RuntimeSetter; + } +} diff --git a/src/main/java/com/caoccao/javet/interop/binding/MethodDescriptor.java b/src/main/java/com/caoccao/javet/interop/binding/MethodDescriptor.java new file mode 100644 index 000000000..816d00c32 --- /dev/null +++ b/src/main/java/com/caoccao/javet/interop/binding/MethodDescriptor.java @@ -0,0 +1,63 @@ +/* + * 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.binding; + +import java.lang.reflect.Method; + +/** + * The type Method descriptor. + */ +public class MethodDescriptor { + /** + * The Method. + */ + protected Method method; + /** + * The This object required. + */ + protected boolean thisObjectRequired; + + /** + * Instantiates a new Method descriptor. + * + * @param method the method + * @param thisObjectRequired the this object required + */ + public MethodDescriptor(Method method, boolean thisObjectRequired) { + this.method = method; + this.thisObjectRequired = thisObjectRequired; + } + + /** + * Gets method. + * + * @return the method + */ + public Method getMethod() { + return method; + } + + /** + * Is this object required boolean. + * + * @return the boolean + */ + public boolean isThisObjectRequired() { + return thisObjectRequired; + } +} diff --git a/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java b/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java index a79d011b1..fec4910d4 100644 --- a/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java +++ b/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java @@ -30,8 +30,9 @@ @SuppressWarnings("unchecked") public class JavetObjectConverter extends JavetPrimitiveConverter { - public static final String PROPERTY_CONSTRUCTOR = "constructor"; - public static final String PROPERTY_NAME = "name"; + protected static final String FUNCTION_ANONYMOUS = "[Function (anonymous)]"; + protected static final String PROPERTY_CONSTRUCTOR = "constructor"; + protected static final String PROPERTY_NAME = "name"; public JavetObjectConverter() { super(); @@ -89,6 +90,8 @@ public Object toObject(V8Value v8Value) throws JavetException { default: break; } + } else if (v8Value instanceof V8ValueFunction) { + return FUNCTION_ANONYMOUS; } else if (v8Value instanceof V8ValueObject) { V8ValueObject v8ValueObject = (V8ValueObject) v8Value; Map map = new HashMap<>(); diff --git a/src/main/java/com/caoccao/javet/utils/JavetPromiseRejectCallback.java b/src/main/java/com/caoccao/javet/utils/JavetPromiseRejectCallback.java index 88d56cfe0..4f72c5199 100644 --- a/src/main/java/com/caoccao/javet/utils/JavetPromiseRejectCallback.java +++ b/src/main/java/com/caoccao/javet/utils/JavetPromiseRejectCallback.java @@ -1,37 +1,37 @@ -/* - * 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.utils; - -import com.caoccao.javet.enums.JavetPromiseRejectEvent; -import com.caoccao.javet.interfaces.IJavetLogger; -import com.caoccao.javet.interfaces.IJavetPromiseRejectCallback; -import com.caoccao.javet.values.V8Value; -import com.caoccao.javet.values.reference.V8ValuePromise; - -public class JavetPromiseRejectCallback implements IJavetPromiseRejectCallback { - protected IJavetLogger logger; - - public JavetPromiseRejectCallback(IJavetLogger logger) { - this.logger = logger; - } - - @Override - public void callback(JavetPromiseRejectEvent event, V8ValuePromise promise, V8Value value) { - logger.logWarn("Received promise reject callback with event {0} {1}.", event.getCode(), event.getName()); - } -} +/* + * 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.utils; + +import com.caoccao.javet.enums.JavetPromiseRejectEvent; +import com.caoccao.javet.interfaces.IJavetLogger; +import com.caoccao.javet.interfaces.IJavetPromiseRejectCallback; +import com.caoccao.javet.values.V8Value; +import com.caoccao.javet.values.reference.V8ValuePromise; + +public class JavetPromiseRejectCallback implements IJavetPromiseRejectCallback { + protected IJavetLogger logger; + + public JavetPromiseRejectCallback(IJavetLogger logger) { + this.logger = logger; + } + + @Override + public void callback(JavetPromiseRejectEvent event, V8ValuePromise promise, V8Value value) { + logger.logWarn("Received promise reject callback with event {0} {1}.", event.getCode(), event.getName()); + } +} diff --git a/src/main/java/com/caoccao/javet/utils/SimpleFreeMarkerFormat.java b/src/main/java/com/caoccao/javet/utils/SimpleFreeMarkerFormat.java index 09c1bc060..adef487ee 100644 --- a/src/main/java/com/caoccao/javet/utils/SimpleFreeMarkerFormat.java +++ b/src/main/java/com/caoccao/javet/utils/SimpleFreeMarkerFormat.java @@ -1,114 +1,114 @@ -/* - * 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.utils; - -import java.util.Map; - -public final class SimpleFreeMarkerFormat { - - public static final String STRING_NULL = ""; - private static final char CHAR_DOLLAR = '$'; - private static final char CHAR_VARIABLE_CLOSE = '}'; - private static final char CHAR_VARIABLE_OPEN = '{'; - - public static String format(final String format, final Map parameters) { - if (format == null || format.length() == 0 || parameters == null || parameters.isEmpty()) { - return format; - } - final int length = format.length(); - StringBuilder stringBuilderMessage = new StringBuilder(); - StringBuilder stringBuilderVariable = new StringBuilder(); - State state = State.Text; - for (int i = 0; i < length; ++i) { - final char c = format.charAt(i); - switch (c) { - case CHAR_DOLLAR: - switch (state) { - case Text: - state = State.Dollar; - break; - case Dollar: - state = State.Text; - stringBuilderMessage.append(CHAR_DOLLAR).append(c); - break; - case Variable: - stringBuilderVariable.append(c); - break; - } - break; - case CHAR_VARIABLE_OPEN: - switch (state) { - case Dollar: - state = State.Variable; - break; - case Variable: - stringBuilderVariable.append(c); - break; - default: - state = State.Text; - stringBuilderMessage.append(c); - break; - } - break; - case CHAR_VARIABLE_CLOSE: - if (state == State.Variable) { - String variableName = stringBuilderVariable.toString(); - Object parameter = parameters.get(variableName); - if (parameter == null) { - parameter = STRING_NULL; - } - stringBuilderMessage.append(parameter); - stringBuilderVariable.setLength(0); - state = State.Text; - } else { - stringBuilderMessage.append(c); - } - break; - default: - switch (state) { - case Dollar: - state = State.Text; - stringBuilderMessage.append(CHAR_DOLLAR).append(c); - break; - case Variable: - stringBuilderVariable.append(c); - break; - default: - stringBuilderMessage.append(c); - break; - } - break; - } - } - switch (state) { - case Dollar: - stringBuilderMessage.append(CHAR_DOLLAR); - break; - case Variable: - stringBuilderMessage.append(CHAR_DOLLAR).append(CHAR_VARIABLE_OPEN).append(stringBuilderVariable); - break; - } - return stringBuilderMessage.toString(); - } - - enum State { - Text, - Dollar, - Variable, - } -} +/* + * 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.utils; + +import java.util.Map; + +public final class SimpleFreeMarkerFormat { + + public static final String STRING_NULL = ""; + private static final char CHAR_DOLLAR = '$'; + private static final char CHAR_VARIABLE_CLOSE = '}'; + private static final char CHAR_VARIABLE_OPEN = '{'; + + public static String format(final String format, final Map parameters) { + if (format == null || format.length() == 0 || parameters == null || parameters.isEmpty()) { + return format; + } + final int length = format.length(); + StringBuilder stringBuilderMessage = new StringBuilder(); + StringBuilder stringBuilderVariable = new StringBuilder(); + State state = State.Text; + for (int i = 0; i < length; ++i) { + final char c = format.charAt(i); + switch (c) { + case CHAR_DOLLAR: + switch (state) { + case Text: + state = State.Dollar; + break; + case Dollar: + state = State.Text; + stringBuilderMessage.append(CHAR_DOLLAR).append(c); + break; + case Variable: + stringBuilderVariable.append(c); + break; + } + break; + case CHAR_VARIABLE_OPEN: + switch (state) { + case Dollar: + state = State.Variable; + break; + case Variable: + stringBuilderVariable.append(c); + break; + default: + state = State.Text; + stringBuilderMessage.append(c); + break; + } + break; + case CHAR_VARIABLE_CLOSE: + if (state == State.Variable) { + String variableName = stringBuilderVariable.toString(); + Object parameter = parameters.get(variableName); + if (parameter == null) { + parameter = STRING_NULL; + } + stringBuilderMessage.append(parameter); + stringBuilderVariable.setLength(0); + state = State.Text; + } else { + stringBuilderMessage.append(c); + } + break; + default: + switch (state) { + case Dollar: + state = State.Text; + stringBuilderMessage.append(CHAR_DOLLAR).append(c); + break; + case Variable: + stringBuilderVariable.append(c); + break; + default: + stringBuilderMessage.append(c); + break; + } + break; + } + } + switch (state) { + case Dollar: + stringBuilderMessage.append(CHAR_DOLLAR); + break; + case Variable: + stringBuilderMessage.append(CHAR_DOLLAR).append(CHAR_VARIABLE_OPEN).append(stringBuilderVariable); + break; + } + return stringBuilderMessage.toString(); + } + + enum State { + Text, + Dollar, + Variable, + } +} diff --git a/src/main/java/com/caoccao/javet/utils/SimpleMap.java b/src/main/java/com/caoccao/javet/utils/SimpleMap.java index 380bae64f..adb0de2b6 100644 --- a/src/main/java/com/caoccao/javet/utils/SimpleMap.java +++ b/src/main/java/com/caoccao/javet/utils/SimpleMap.java @@ -1,148 +1,148 @@ -/* - * 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.utils; - -import java.util.HashMap; -import java.util.Map; - -/** - * The type Simple map is a polyfill because Map.of is not available at JDK 8 . - */ -public final class SimpleMap { - - public static Map of( - K k1, V v1 - ) { - return new HashMap() {{ - put(k1, v1); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3, - K k4, V v4 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - put(k4, v4); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3, - K k4, V v4, - K k5, V v5 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - put(k4, v4); - put(k5, v5); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3, - K k4, V v4, - K k5, V v5, - K k6, V v6 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - put(k4, v4); - put(k5, v5); - put(k6, v6); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3, - K k4, V v4, - K k5, V v5, - K k6, V v6, - K k7, V v7 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - put(k4, v4); - put(k5, v5); - put(k6, v6); - put(k7, v7); - }}; - } - - public static Map of( - K k1, V v1, - K k2, V v2, - K k3, V v3, - K k4, V v4, - K k5, V v5, - K k6, V v6, - K k7, V v7, - K k8, V v8 - ) { - return new HashMap() {{ - put(k1, v1); - put(k2, v2); - put(k3, v3); - put(k4, v4); - put(k5, v5); - put(k6, v6); - put(k7, v7); - put(k8, v8); - }}; - } - -} +/* + * 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.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * The type Simple map is a polyfill because Map.of is not available at JDK 8 . + */ +public final class SimpleMap { + + public static Map of( + K k1, V v1 + ) { + return new HashMap() {{ + put(k1, v1); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3, + K k4, V v4 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + put(k4, v4); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3, + K k4, V v4, + K k5, V v5 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + put(k4, v4); + put(k5, v5); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3, + K k4, V v4, + K k5, V v5, + K k6, V v6 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + put(k4, v4); + put(k5, v5); + put(k6, v6); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3, + K k4, V v4, + K k5, V v5, + K k6, V v6, + K k7, V v7 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + put(k4, v4); + put(k5, v5); + put(k6, v6); + put(k7, v7); + }}; + } + + public static Map of( + K k1, V v1, + K k2, V v2, + K k3, V v3, + K k4, V v4, + K k5, V v5, + K k6, V v6, + K k7, V v7, + K k8, V v8 + ) { + return new HashMap() {{ + put(k1, v1); + put(k2, v2); + put(k3, v3); + put(k4, v4); + put(k5, v5); + put(k6, v6); + put(k7, v7); + put(k8, v8); + }}; + } + +} diff --git a/src/main/java/com/caoccao/javet/values/reference/V8ValueGlobalObject.java b/src/main/java/com/caoccao/javet/values/reference/V8ValueGlobalObject.java index c9c6015e1..b306379b0 100644 --- a/src/main/java/com/caoccao/javet/values/reference/V8ValueGlobalObject.java +++ b/src/main/java/com/caoccao/javet/values/reference/V8ValueGlobalObject.java @@ -20,6 +20,7 @@ import com.caoccao.javet.annotations.CheckReturnValue; import com.caoccao.javet.exceptions.JavetException; import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInJson; +import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInObject; import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInPromise; /** @@ -34,6 +35,7 @@ public final class V8ValueGlobalObject extends V8ValueObject { public static final String PROPERTY_JSON = "JSON"; public static final String PROPERTY_PROMISE = "Promise"; + public static final String PROPERTY_OBJECT = "Object"; /** * Instantiates a new V8 value global object. @@ -60,13 +62,19 @@ public void close(boolean forceClose) throws JavetException { } @CheckReturnValue - public V8ValueBuiltInJson getJson() throws JavetException { + public V8ValueBuiltInJson getBuiltInJson() throws JavetException { V8ValueObject v8ValueObject = get(PROPERTY_JSON); return v8Runtime.decorateV8Value(new V8ValueBuiltInJson(v8ValueObject.getHandle())); } @CheckReturnValue - public V8ValueBuiltInPromise getPromise() throws JavetException { + public V8ValueBuiltInObject getBuiltInObject() throws JavetException { + V8ValueObject v8ValueObject = get(PROPERTY_OBJECT); + return v8Runtime.decorateV8Value(new V8ValueBuiltInObject(v8ValueObject.getHandle())); + } + + @CheckReturnValue + public V8ValueBuiltInPromise getBuiltInPromise() throws JavetException { V8ValueObject v8ValueObject = get(PROPERTY_PROMISE); return v8Runtime.decorateV8Value(new V8ValueBuiltInPromise(v8ValueObject.getHandle())); } diff --git a/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java b/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java index fc235258d..cebcd2875 100644 --- a/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java +++ b/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java @@ -29,6 +29,8 @@ import com.caoccao.javet.interfaces.IJavetUniConsumer; import com.caoccao.javet.interfaces.IJavetUniIndexedConsumer; import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.interop.binding.BindingContext; +import com.caoccao.javet.interop.binding.MethodDescriptor; import com.caoccao.javet.utils.JavetCallbackContext; import com.caoccao.javet.utils.SimpleMap; import com.caoccao.javet.values.V8Value; @@ -56,59 +58,19 @@ protected V8ValueObject(long handle) { @Override public List bind(Object callbackReceiver) throws JavetException { - Map propertyGetterMap = new HashMap<>(); - Map propertySetterMap = new HashMap<>(); - Map functionMap = new HashMap<>(); - for (Method method : callbackReceiver.getClass().getMethods()) { - if (method.isAnnotationPresent(V8Property.class)) { - V8Property v8Property = method.getAnnotation(V8Property.class); - String propertyName = v8Property.name(); - if (propertyName.length() == 0) { - String methodName = method.getName(); - if (methodName.startsWith(METHOD_PREFIX_IS)) { - propertyName = methodName.substring(METHOD_PREFIX_IS.length()); - } else if (methodName.startsWith(METHOD_PREFIX_GET)) { - propertyName = methodName.substring(METHOD_PREFIX_GET.length()); - } else if (methodName.startsWith(METHOD_PREFIX_SET)) { - propertyName = methodName.substring(METHOD_PREFIX_SET.length()); - } - if (propertyName.length() > 0) { - propertyName = propertyName.substring(0, 1).toLowerCase(Locale.ROOT) + propertyName.substring(1); - } - } - if (propertyName.length() > 0) { - final int expectedGetterParameterCount = v8Property.thisObjectRequired() ? 1 : 0; - final int expectedSetterParameterCount = v8Property.thisObjectRequired() ? 2 : 1; - if (method.getParameterCount() == expectedGetterParameterCount) { - // Duplicated property name will be dropped. - if (!propertyGetterMap.containsKey(propertyName)) { - propertyGetterMap.put(propertyName, new MethodDescriptor(method, v8Property.thisObjectRequired())); - } - } else if (method.getParameterCount() == expectedSetterParameterCount) { - // Duplicated property name will be dropped. - if (!propertySetterMap.containsKey(propertyName)) { - propertySetterMap.put(propertyName, new MethodDescriptor(method, v8Property.thisObjectRequired())); - } - } else { - throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, - SimpleMap.of( - JavetError.PARAMETER_METHOD_NAME, method.getName(), - JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, expectedGetterParameterCount, - JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); - } - } - } else if (method.isAnnotationPresent(V8Function.class)) { - V8Function v8Function = method.getAnnotation(V8Function.class); - String functionName = v8Function.name(); - if (functionName.length() == 0) { - functionName = method.getName(); - } - // Duplicated function will be dropped. - if (!functionMap.containsKey(functionName)) { - functionMap.put(functionName, new MethodDescriptor(method, v8Function.thisObjectRequired())); - } - } else { - bindV8Runtime(callbackReceiver, method); + Objects.requireNonNull(callbackReceiver); + BindingContext bindingContext = getBindingContext(callbackReceiver.getClass()); + Map propertyGetterMap = bindingContext.getPropertyGetterMap(); + Map propertySetterMap = bindingContext.getPropertySetterMap(); + Map functionMap = bindingContext.getFunctionMap(); + if (bindingContext.getV8RuntimeSetter() != null) { + try { + bindingContext.getV8RuntimeSetter().invoke(callbackReceiver, getV8Runtime()); + } catch (Exception e) { + throw new JavetException( + JavetError.CallbackInjectionFailure, + SimpleMap.of(JavetError.PARAMETER_MESSAGE, e.getMessage()), + e); } } List javetCallbackContexts = new ArrayList<>(); @@ -119,16 +81,16 @@ public List bind(Object callbackReceiver) throws JavetExce try { // Static method needs to be identified. JavetCallbackContext javetCallbackContextGetter = new JavetCallbackContext( - Modifier.isStatic(getterMethodDescriptor.method.getModifiers()) ? null : callbackReceiver, - getterMethodDescriptor.method, getterMethodDescriptor.thisObjectRequired); + Modifier.isStatic(getterMethodDescriptor.getMethod().getModifiers()) ? null : callbackReceiver, + getterMethodDescriptor.getMethod(), getterMethodDescriptor.isThisObjectRequired()); javetCallbackContexts.add(javetCallbackContextGetter); JavetCallbackContext javetCallbackContextSetter = null; if (propertySetterMap.containsKey(propertyName)) { MethodDescriptor setterMethodDescriptor = propertySetterMap.get(propertyName); // Static method needs to be identified. javetCallbackContextSetter = new JavetCallbackContext( - Modifier.isStatic(setterMethodDescriptor.method.getModifiers()) ? null : callbackReceiver, - setterMethodDescriptor.method, setterMethodDescriptor.thisObjectRequired); + Modifier.isStatic(setterMethodDescriptor.getMethod().getModifiers()) ? null : callbackReceiver, + setterMethodDescriptor.getMethod(), setterMethodDescriptor.isThisObjectRequired()); javetCallbackContexts.add(javetCallbackContextSetter); } bindProperty(propertyName, javetCallbackContextGetter, javetCallbackContextSetter); @@ -136,7 +98,7 @@ public List bind(Object callbackReceiver) throws JavetExce throw new JavetException( JavetError.CallbackRegistrationFailure, SimpleMap.of( - JavetError.PARAMETER_METHOD_NAME, getterMethodDescriptor.method.getName(), + JavetError.PARAMETER_METHOD_NAME, getterMethodDescriptor.getMethod().getName(), JavetError.PARAMETER_MESSAGE, e.getMessage()), e); } @@ -148,15 +110,15 @@ public List bind(Object callbackReceiver) throws JavetExce try { // Static method needs to be identified. JavetCallbackContext javetCallbackContext = new JavetCallbackContext( - Modifier.isStatic(methodDescriptor.method.getModifiers()) ? null : callbackReceiver, - methodDescriptor.method, methodDescriptor.thisObjectRequired); + Modifier.isStatic(methodDescriptor.getMethod().getModifiers()) ? null : callbackReceiver, + methodDescriptor.getMethod(), methodDescriptor.isThisObjectRequired()); bindFunction(entry.getKey(), javetCallbackContext); javetCallbackContexts.add(javetCallbackContext); } catch (Exception e) { throw new JavetException( JavetError.CallbackRegistrationFailure, SimpleMap.of( - JavetError.PARAMETER_METHOD_NAME, methodDescriptor.method.getName(), + JavetError.PARAMETER_METHOD_NAME, methodDescriptor.getMethod().getName(), JavetError.PARAMETER_MESSAGE, e.getMessage()), e); } @@ -189,33 +151,6 @@ public boolean bindProperty( return v8Runtime.setAccessor(this, propertyName, javetCallbackContextGetter, javetCallbackContextSetter); } - protected void bindV8Runtime(Object callbackReceiver, Method method) throws JavetException { - if (method.isAnnotationPresent(V8RuntimeSetter.class)) { - if (method.getParameterCount() != 1) { - throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, - SimpleMap.of( - JavetError.PARAMETER_METHOD_NAME, method.getName(), - JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, 1, - JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); - } - if (!V8Runtime.class.isAssignableFrom(method.getParameterTypes()[0])) { - throw new JavetException( - JavetError.CallbackSignatureParameterTypeMismatch, - SimpleMap.of( - JavetError.PARAMETER_EXPECTED_PARAMETER_TYPE, V8Runtime.class, - JavetError.PARAMETER_ACTUAL_PARAMETER_TYPE, method.getParameterTypes()[0])); - } - try { - method.invoke(callbackReceiver, getV8Runtime()); - } catch (Exception e) { - throw new JavetException( - JavetError.CallbackInjectionFailure, - SimpleMap.of(JavetError.PARAMETER_MESSAGE, e.getMessage()), - e); - } - } - } - @Override public boolean delete(Object key) throws JavetException { checkV8Runtime(); @@ -277,6 +212,85 @@ public T get(Object key) throws JavetException { } } + protected BindingContext getBindingContext(Class callbackReceiverClass) throws JavetException { + WeakHashMap, BindingContext> bindingContextWeakHashMap = v8Runtime.getBindingContextWeakHashMap(); + BindingContext bindingContext = bindingContextWeakHashMap.get(callbackReceiverClass); + if (bindingContext == null) { + bindingContext = new BindingContext(); + Map propertyGetterMap = bindingContext.getPropertyGetterMap(); + Map propertySetterMap = bindingContext.getPropertySetterMap(); + Map functionMap = bindingContext.getFunctionMap(); + for (Method method : callbackReceiverClass.getMethods()) { + if (method.isAnnotationPresent(V8Property.class)) { + V8Property v8Property = method.getAnnotation(V8Property.class); + String propertyName = v8Property.name(); + if (propertyName.length() == 0) { + String methodName = method.getName(); + if (methodName.startsWith(METHOD_PREFIX_IS)) { + propertyName = methodName.substring(METHOD_PREFIX_IS.length()); + } else if (methodName.startsWith(METHOD_PREFIX_GET)) { + propertyName = methodName.substring(METHOD_PREFIX_GET.length()); + } else if (methodName.startsWith(METHOD_PREFIX_SET)) { + propertyName = methodName.substring(METHOD_PREFIX_SET.length()); + } + if (propertyName.length() > 0) { + propertyName = propertyName.substring(0, 1).toLowerCase(Locale.ROOT) + propertyName.substring(1); + } + } + if (propertyName.length() > 0) { + final int expectedGetterParameterCount = v8Property.thisObjectRequired() ? 1 : 0; + final int expectedSetterParameterCount = v8Property.thisObjectRequired() ? 2 : 1; + if (method.getParameterCount() == expectedGetterParameterCount) { + // Duplicated property name will be dropped. + if (!propertyGetterMap.containsKey(propertyName)) { + propertyGetterMap.put(propertyName, new MethodDescriptor(method, v8Property.thisObjectRequired())); + } + } else if (method.getParameterCount() == expectedSetterParameterCount) { + // Duplicated property name will be dropped. + if (!propertySetterMap.containsKey(propertyName)) { + propertySetterMap.put(propertyName, new MethodDescriptor(method, v8Property.thisObjectRequired())); + } + } else { + throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, + SimpleMap.of( + JavetError.PARAMETER_METHOD_NAME, method.getName(), + JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, expectedGetterParameterCount, + JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); + } + } + } else if (method.isAnnotationPresent(V8Function.class)) { + V8Function v8Function = method.getAnnotation(V8Function.class); + String functionName = v8Function.name(); + if (functionName.length() == 0) { + functionName = method.getName(); + } + // Duplicated function will be dropped. + if (!functionMap.containsKey(functionName)) { + functionMap.put(functionName, new MethodDescriptor(method, v8Function.thisObjectRequired())); + } + } else if (method.isAnnotationPresent(V8RuntimeSetter.class)) { + if (method.getParameterCount() != 1) { + throw new JavetException(JavetError.CallbackSignatureParameterSizeMismatch, + SimpleMap.of( + JavetError.PARAMETER_METHOD_NAME, method.getName(), + JavetError.PARAMETER_EXPECTED_PARAMETER_SIZE, 1, + JavetError.PARAMETER_ACTUAL_PARAMETER_SIZE, method.getParameterCount())); + } + if (!V8Runtime.class.isAssignableFrom(method.getParameterTypes()[0])) { + throw new JavetException( + JavetError.CallbackSignatureParameterTypeMismatch, + SimpleMap.of( + JavetError.PARAMETER_EXPECTED_PARAMETER_TYPE, V8Runtime.class, + JavetError.PARAMETER_ACTUAL_PARAMETER_TYPE, method.getParameterTypes()[0])); + } + bindingContext.setV8RuntimeSetter(method); + } + } + bindingContextWeakHashMap.put(callbackReceiverClass, bindingContext); + } + return bindingContext; + } + @Override public int getIdentityHash() throws JavetException { checkV8Runtime(); @@ -398,7 +412,7 @@ public boolean strictEquals(V8Value v8Value) throws JavetException { public String toJsonString() { try { checkV8Runtime(); - try (V8ValueBuiltInJson v8ValueBuiltInJson = v8Runtime.getGlobalObject().getJson()) { + try (V8ValueBuiltInJson v8ValueBuiltInJson = v8Runtime.getGlobalObject().getBuiltInJson()) { return v8ValueBuiltInJson.stringify(this); } } catch (JavetException e) { @@ -415,14 +429,4 @@ public String toProtoString() { return e.getMessage(); } } - - private static class MethodDescriptor { - public Method method; - public boolean thisObjectRequired; - - public MethodDescriptor(Method method, boolean thisObjectRequired) { - this.method = method; - this.thisObjectRequired = thisObjectRequired; - } - } } diff --git a/src/main/java/com/caoccao/javet/values/reference/builtin/V8ValueBuiltInObject.java b/src/main/java/com/caoccao/javet/values/reference/builtin/V8ValueBuiltInObject.java new file mode 100644 index 000000000..98f7ae072 --- /dev/null +++ b/src/main/java/com/caoccao/javet/values/reference/builtin/V8ValueBuiltInObject.java @@ -0,0 +1,44 @@ +/* + * 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.values.reference.builtin; + +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.values.reference.V8ValueObject; + +import java.util.Objects; + +@SuppressWarnings("unchecked") +public class V8ValueBuiltInObject extends V8ValueObject { + + public static final String FUNCTION_ASSIGN = "assign"; + + public V8ValueBuiltInObject(long handle) { + super(handle); + } + + public V8ValueObject assign(V8ValueObject v8Value1, V8ValueObject v8Value2) throws JavetException { + Objects.requireNonNull(v8Value1); + Objects.requireNonNull(v8Value2); + return invoke(FUNCTION_ASSIGN, v8Value1, v8Value2); + } + + @Override + public V8ValueBuiltInObject toClone() throws JavetException { + return this; + } +} diff --git a/src/main/java/com/caoccao/javet/values/virtual/V8VirtualValue.java b/src/main/java/com/caoccao/javet/values/virtual/V8VirtualValue.java index 0ffc41db1..d7bb6e726 100644 --- a/src/main/java/com/caoccao/javet/values/virtual/V8VirtualValue.java +++ b/src/main/java/com/caoccao/javet/values/virtual/V8VirtualValue.java @@ -1,51 +1,51 @@ -/* - * 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.values.virtual; - -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interfaces.IJavetClosable; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.values.V8Value; - -@SuppressWarnings("unchecked") -public class V8VirtualValue implements IJavetClosable { - protected boolean converted; - protected V8Value value; - - public V8VirtualValue(V8Runtime v8Runtime, Object object) throws JavetException { - if (object instanceof V8Value) { - converted = false; - value = (V8Value) object; - } else { - converted = true; - value = v8Runtime.toV8Value(object); - } - } - - @Override - public void close() throws JavetException { - if (converted) { - JavetResourceUtils.safeClose(value); - } - } - - public T get() { - return (T) value; - } -} +/* + * 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.values.virtual; + +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interfaces.IJavetClosable; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.utils.JavetResourceUtils; +import com.caoccao.javet.values.V8Value; + +@SuppressWarnings("unchecked") +public class V8VirtualValue implements IJavetClosable { + protected boolean converted; + protected V8Value value; + + public V8VirtualValue(V8Runtime v8Runtime, Object object) throws JavetException { + if (object instanceof V8Value) { + converted = false; + value = (V8Value) object; + } else { + converted = true; + value = v8Runtime.toV8Value(object); + } + } + + @Override + public void close() throws JavetException { + if (converted) { + JavetResourceUtils.safeClose(value); + } + } + + public T get() { + return (T) value; + } +} diff --git a/src/test/java/com/caoccao/javet/exceptions/TestJavetError.java b/src/test/java/com/caoccao/javet/exceptions/TestJavetError.java index c39269391..bb08c9269 100644 --- a/src/test/java/com/caoccao/javet/exceptions/TestJavetError.java +++ b/src/test/java/com/caoccao/javet/exceptions/TestJavetError.java @@ -1,116 +1,116 @@ -/* - * 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 com.caoccao.javet.utils.JavetOSUtils; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class TestJavetError { - @Test - public void generateDocument() throws IllegalAccessException, IOException { - String startSign = "\n.. Error Codes Begin\n\n\n"; - String endSign = "\n.. Error Codes End\n"; - File file = new File(JavetOSUtils.WORKING_DIRECTORY, "docs/reference/error_codes.rst"); - assertTrue(file.exists()); - assertTrue(file.canRead()); - assertTrue(file.canWrite()); - byte[] originalBuffer = Files.readAllBytes(file.toPath()); - String fileContent = new String(originalBuffer, StandardCharsets.UTF_8); - assertNotNull(fileContent); - final int startPosition = fileContent.indexOf(startSign) + startSign.length(); - final int endPosition = fileContent.lastIndexOf(endSign) + 1; - assertTrue(endPosition >= startPosition && startPosition > 0); - String[] headerRow = new String[]{"Code", "Type", "Name", "Format"}; - int[] maxLengths = Arrays.stream(headerRow).mapToInt(cell -> cell.length()).toArray(); - Map table = new TreeMap<>(); - Class javetErrorClass = JavetError.class; - for (Field field : javetErrorClass.getDeclaredFields()) { - final int modifiers = field.getModifiers(); - if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && Modifier.isFinal(modifiers) - && field.getType() == javetErrorClass) { - JavetError javetError = (JavetError) field.get(null); - String[] row = new String[headerRow.length]; - int code = javetError.getCode(); - table.put(code, row); - String cell = Integer.toString(code); - if (maxLengths[0] < cell.length()) { - maxLengths[0] = cell.length(); - } - row[0] = cell; - cell = javetError.getType().name(); - if (maxLengths[1] < cell.length()) { - maxLengths[1] = cell.length(); - } - row[1] = cell; - cell = field.getName(); - if (maxLengths[2] < cell.length()) { - maxLengths[2] = cell.length(); - } - row[2] = cell; - cell = javetError.getFormat(); - if (maxLengths[3] < cell.length()) { - maxLengths[3] = cell.length(); - } - row[3] = cell; - } - } - assertTrue(table.size() > 0); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(fileContent.substring(0, startPosition)); - String separator = String.join(" ", - Arrays.stream(maxLengths) - .mapToObj(length -> String.join("", Collections.nCopies(length, "="))) - .collect(Collectors.toList())); - stringBuilder.append(separator).append("\n"); - stringBuilder.append(String.join(" ", - IntStream.range(0, maxLengths.length) - .mapToObj(i -> String.format("%1$-" + Integer.toString(maxLengths[i]) + "s", headerRow[i])) - .collect(Collectors.toList()))).append("\n"); - stringBuilder.append(separator).append("\n"); - for (String[] row : table.values()) { - stringBuilder.append(String.join(" ", - IntStream.range(0, maxLengths.length) - .mapToObj(i -> String.format("%1$-" + Integer.toString(maxLengths[i]) + "s", row[i])) - .collect(Collectors.toList()))).append("\n"); - } - stringBuilder.append(separator).append("\n\n\n"); - stringBuilder.append(fileContent.substring(endPosition)); - byte[] newBuffer = stringBuilder.toString().getBytes(StandardCharsets.UTF_8); - if (!Arrays.equals(originalBuffer, newBuffer)) { - // Only generate document when content is changed. - Files.write(file.toPath(), newBuffer, StandardOpenOption.CREATE); - } - } -} +/* + * 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 com.caoccao.javet.utils.JavetOSUtils; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TestJavetError { + @Test + public void generateDocument() throws IllegalAccessException, IOException { + String startSign = "\n.. Error Codes Begin\n\n\n"; + String endSign = "\n.. Error Codes End\n"; + File file = new File(JavetOSUtils.WORKING_DIRECTORY, "docs/reference/error_codes.rst"); + assertTrue(file.exists()); + assertTrue(file.canRead()); + assertTrue(file.canWrite()); + byte[] originalBuffer = Files.readAllBytes(file.toPath()); + String fileContent = new String(originalBuffer, StandardCharsets.UTF_8); + assertNotNull(fileContent); + final int startPosition = fileContent.indexOf(startSign) + startSign.length(); + final int endPosition = fileContent.lastIndexOf(endSign) + 1; + assertTrue(endPosition >= startPosition && startPosition > 0); + String[] headerRow = new String[]{"Code", "Type", "Name", "Format"}; + int[] maxLengths = Arrays.stream(headerRow).mapToInt(cell -> cell.length()).toArray(); + Map table = new TreeMap<>(); + Class javetErrorClass = JavetError.class; + for (Field field : javetErrorClass.getDeclaredFields()) { + final int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && Modifier.isFinal(modifiers) + && field.getType() == javetErrorClass) { + JavetError javetError = (JavetError) field.get(null); + String[] row = new String[headerRow.length]; + int code = javetError.getCode(); + table.put(code, row); + String cell = Integer.toString(code); + if (maxLengths[0] < cell.length()) { + maxLengths[0] = cell.length(); + } + row[0] = cell; + cell = javetError.getType().name(); + if (maxLengths[1] < cell.length()) { + maxLengths[1] = cell.length(); + } + row[1] = cell; + cell = field.getName(); + if (maxLengths[2] < cell.length()) { + maxLengths[2] = cell.length(); + } + row[2] = cell; + cell = javetError.getFormat(); + if (maxLengths[3] < cell.length()) { + maxLengths[3] = cell.length(); + } + row[3] = cell; + } + } + assertTrue(table.size() > 0); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(fileContent.substring(0, startPosition)); + String separator = String.join(" ", + Arrays.stream(maxLengths) + .mapToObj(length -> String.join("", Collections.nCopies(length, "="))) + .collect(Collectors.toList())); + stringBuilder.append(separator).append("\n"); + stringBuilder.append(String.join(" ", + IntStream.range(0, maxLengths.length) + .mapToObj(i -> String.format("%1$-" + Integer.toString(maxLengths[i]) + "s", headerRow[i])) + .collect(Collectors.toList()))).append("\n"); + stringBuilder.append(separator).append("\n"); + for (String[] row : table.values()) { + stringBuilder.append(String.join(" ", + IntStream.range(0, maxLengths.length) + .mapToObj(i -> String.format("%1$-" + Integer.toString(maxLengths[i]) + "s", row[i])) + .collect(Collectors.toList()))).append("\n"); + } + stringBuilder.append(separator).append("\n\n\n"); + stringBuilder.append(fileContent.substring(endPosition)); + byte[] newBuffer = stringBuilder.toString().getBytes(StandardCharsets.UTF_8); + if (!Arrays.equals(originalBuffer, newBuffer)) { + // Only generate document when content is changed. + Files.write(file.toPath(), newBuffer, StandardOpenOption.CREATE); + } + } +} diff --git a/src/test/java/com/caoccao/javet/interop/TestV8Locker.java b/src/test/java/com/caoccao/javet/interop/TestV8Locker.java index 36479400e..d0cbf1ce7 100644 --- a/src/test/java/com/caoccao/javet/interop/TestV8Locker.java +++ b/src/test/java/com/caoccao/javet/interop/TestV8Locker.java @@ -1,53 +1,53 @@ -/* - * 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.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetError; -import com.caoccao.javet.exceptions.JavetException; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class TestV8Locker extends BaseTestJavetRuntime { - @Test - public void testExceptionInAcquire() throws JavetException { - try (V8Locker v8Locker = v8Runtime.getV8Locker()) { - assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); - try { - v8Runtime.getV8Locker(); - } catch (JavetException e) { - assertEquals(JavetError.LockAcquisitionFailure, e.getError(), - "Second lock acquisition should fail."); - } - } - } - - @Test - public void testExceptionInClose() throws JavetException { - V8Locker v8Locker = v8Runtime.getV8Locker(); - assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); - v8Locker.close(); - try { - v8Locker.close(); - } catch (JavetException e) { - assertEquals(JavetError.LockReleaseFailure, e.getError(), - "Second lock release should fail."); - } - } -} +/* + * 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.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetError; +import com.caoccao.javet.exceptions.JavetException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestV8Locker extends BaseTestJavetRuntime { + @Test + public void testExceptionInAcquire() throws JavetException { + try (V8Locker v8Locker = v8Runtime.getV8Locker()) { + assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); + try { + v8Runtime.getV8Locker(); + } catch (JavetException e) { + assertEquals(JavetError.LockAcquisitionFailure, e.getError(), + "Second lock acquisition should fail."); + } + } + } + + @Test + public void testExceptionInClose() throws JavetException { + V8Locker v8Locker = v8Runtime.getV8Locker(); + assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); + v8Locker.close(); + try { + v8Locker.close(); + } catch (JavetException e) { + assertEquals(JavetError.LockReleaseFailure, e.getError(), + "Second lock release should fail."); + } + } +} diff --git a/src/test/java/com/caoccao/javet/interop/converters/TestJavetCustomConverter.java b/src/test/java/com/caoccao/javet/interop/converters/TestJavetCustomConverter.java index 660efc6d3..7902d40cb 100644 --- a/src/test/java/com/caoccao/javet/interop/converters/TestJavetCustomConverter.java +++ b/src/test/java/com/caoccao/javet/interop/converters/TestJavetCustomConverter.java @@ -1,133 +1,133 @@ -/* - * 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.converters; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.values.V8Value; -import com.caoccao.javet.values.reference.V8ValueObject; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class TestJavetCustomConverter extends BaseTestJavetRuntime { - @Test - public void testPojo() throws JavetException, JsonProcessingException { - Pojo[] pojoArray = new Pojo[]{ - new Pojo("Tom", "CEO"), - new Pojo("Jerry", "CFO")}; - PojoConverter converter = new PojoConverter(); - v8Runtime.setConverter(converter); - v8Runtime.getGlobalObject().set("pojoArray", pojoArray); - ObjectMapper objectMapper = new ObjectMapper(); - assertEquals( - "[{\"name\":\"Tom\",\"value\":\"CEO\"},{\"name\":\"Jerry\",\"value\":\"CFO\"}]", - objectMapper.writeValueAsString(v8Runtime.getExecutor("pojoArray;").executeObject())); - } - - @SuppressWarnings("unchecked") - static class PojoConverter extends JavetObjectConverter { - public static final String METHOD_PREFIX_GET = "get"; - public static final String METHOD_PREFIX_IS = "is"; - protected static final Set EXCLUDED_METHODS; - - static { - EXCLUDED_METHODS = new HashSet<>(); - for (Method method : Object.class.getMethods()) { - if (method.getParameterCount() == 0) { - String methodName = method.getName(); - if (methodName.startsWith(METHOD_PREFIX_IS) || methodName.startsWith(METHOD_PREFIX_GET)) { - EXCLUDED_METHODS.add(methodName); - } - } - } - } - - @Override - public V8Value toV8Value(V8Runtime v8Runtime, Object object) throws JavetException { - V8Value v8Value = super.toV8Value(v8Runtime, object); - if (v8Value != null && !(v8Value.isUndefined())) { - return v8Value; - } - Class objectClass = object.getClass(); - V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject(); - for (Method method : objectClass.getMethods()) { - if (method.getParameterCount() == 0) { - String methodName = method.getName(); - String propertyName = null; - if (methodName.startsWith(METHOD_PREFIX_IS) && !EXCLUDED_METHODS.contains(methodName) - && methodName.length() > METHOD_PREFIX_IS.length()) { - propertyName = methodName.substring(METHOD_PREFIX_IS.length(), METHOD_PREFIX_IS.length() + 1).toLowerCase(Locale.ROOT) - + methodName.substring(METHOD_PREFIX_IS.length() + 1); - } else if (methodName.startsWith(METHOD_PREFIX_GET) && !EXCLUDED_METHODS.contains(methodName) - && methodName.length() > METHOD_PREFIX_GET.length()) { - propertyName = methodName.substring(METHOD_PREFIX_GET.length(), METHOD_PREFIX_GET.length() + 1).toLowerCase(Locale.ROOT) - + methodName.substring(METHOD_PREFIX_GET.length() + 1); - } - if (propertyName != null) { - try (V8Value v8ValueTemp = toV8Value(v8Runtime, method.invoke(object))) { - v8ValueObject.set(propertyName, v8ValueTemp); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - v8Value = v8ValueObject; - return v8Runtime.decorateV8Value(v8Value); - } - } - - class Pojo { - private String name; - private String value; - - public Pojo() { - this(null, null); - } - - public Pojo(String name, String value) { - this.name = name; - this.value = value; - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - public void setName(String name) { - this.name = name; - } - - public void setValue(String value) { - this.value = value; - } - } -} +/* + * 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.converters; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.values.V8Value; +import com.caoccao.javet.values.reference.V8ValueObject; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestJavetCustomConverter extends BaseTestJavetRuntime { + @Test + public void testPojo() throws JavetException, JsonProcessingException { + Pojo[] pojoArray = new Pojo[]{ + new Pojo("Tom", "CEO"), + new Pojo("Jerry", "CFO")}; + PojoConverter converter = new PojoConverter(); + v8Runtime.setConverter(converter); + v8Runtime.getGlobalObject().set("pojoArray", pojoArray); + ObjectMapper objectMapper = new ObjectMapper(); + assertEquals( + "[{\"name\":\"Tom\",\"value\":\"CEO\"},{\"name\":\"Jerry\",\"value\":\"CFO\"}]", + objectMapper.writeValueAsString(v8Runtime.getExecutor("pojoArray;").executeObject())); + } + + @SuppressWarnings("unchecked") + static class PojoConverter extends JavetObjectConverter { + public static final String METHOD_PREFIX_GET = "get"; + public static final String METHOD_PREFIX_IS = "is"; + protected static final Set EXCLUDED_METHODS; + + static { + EXCLUDED_METHODS = new HashSet<>(); + for (Method method : Object.class.getMethods()) { + if (method.getParameterCount() == 0) { + String methodName = method.getName(); + if (methodName.startsWith(METHOD_PREFIX_IS) || methodName.startsWith(METHOD_PREFIX_GET)) { + EXCLUDED_METHODS.add(methodName); + } + } + } + } + + @Override + public V8Value toV8Value(V8Runtime v8Runtime, Object object) throws JavetException { + V8Value v8Value = super.toV8Value(v8Runtime, object); + if (v8Value != null && !(v8Value.isUndefined())) { + return v8Value; + } + Class objectClass = object.getClass(); + V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject(); + for (Method method : objectClass.getMethods()) { + if (method.getParameterCount() == 0) { + String methodName = method.getName(); + String propertyName = null; + if (methodName.startsWith(METHOD_PREFIX_IS) && !EXCLUDED_METHODS.contains(methodName) + && methodName.length() > METHOD_PREFIX_IS.length()) { + propertyName = methodName.substring(METHOD_PREFIX_IS.length(), METHOD_PREFIX_IS.length() + 1).toLowerCase(Locale.ROOT) + + methodName.substring(METHOD_PREFIX_IS.length() + 1); + } else if (methodName.startsWith(METHOD_PREFIX_GET) && !EXCLUDED_METHODS.contains(methodName) + && methodName.length() > METHOD_PREFIX_GET.length()) { + propertyName = methodName.substring(METHOD_PREFIX_GET.length(), METHOD_PREFIX_GET.length() + 1).toLowerCase(Locale.ROOT) + + methodName.substring(METHOD_PREFIX_GET.length() + 1); + } + if (propertyName != null) { + try (V8Value v8ValueTemp = toV8Value(v8Runtime, method.invoke(object))) { + v8ValueObject.set(propertyName, v8ValueTemp); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + v8Value = v8ValueObject; + return v8Runtime.decorateV8Value(v8Value); + } + } + + class Pojo { + private String name; + private String value; + + public Pojo() { + this(null, null); + } + + public Pojo(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public void setName(String name) { + this.name = name; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java b/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java index 1fa4f3527..289e7fb62 100644 --- a/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java +++ b/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java @@ -1,249 +1,260 @@ -/* - * 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.converters; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.entities.JavetEntityMap; -import com.caoccao.javet.enums.V8ValueReferenceType; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.utils.JavetDateTimeUtils; -import com.caoccao.javet.values.reference.*; -import org.junit.jupiter.api.Test; - -import java.time.ZonedDateTime; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; - -@SuppressWarnings("unchecked") -public class TestJavetObjectConverter extends BaseTestJavetRuntime { - @Test - public void testArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - try (V8ValueArray v8ValueArray = v8Runtime.createV8ValueArray()) { - v8ValueArray.push("abc"); - v8ValueArray.push(123); - List list = (List) converter.toObject(v8ValueArray); - assertEquals(2, list.size()); - assertEquals("abc", list.get(0)); - assertEquals(123, list.get(1)); - } - // ArrayList - try (V8ValueArray v8ValueArray = converter.toV8Value( - v8Runtime, Arrays.asList("abc", 123))) { - assertEquals(2, v8ValueArray.getLength()); - assertEquals("abc", v8ValueArray.getString(0)); - assertEquals(123, v8ValueArray.getInteger(1)); - } - // boolean[] - try (V8ValueArray v8ValueArray = converter.toV8Value( - v8Runtime, new boolean[]{true, false})) { - assertEquals(2, v8ValueArray.getLength()); - assertEquals(true, v8ValueArray.getBoolean(0)); - assertEquals(false, v8ValueArray.getBoolean(1)); - } - // String[] - try (V8ValueArray v8ValueArray = converter.toV8Value( - v8Runtime, new String[]{"abc", "def"})) { - assertEquals(2, v8ValueArray.getLength()); - assertEquals("abc", v8ValueArray.getString(0)); - assertEquals("def", v8ValueArray.getString(1)); - } - // ZonedDateTime[] - try (V8ValueArray v8ValueArray = converter.toV8Value( - v8Runtime, new ZonedDateTime[]{ - JavetDateTimeUtils.toZonedDateTime(123L), - JavetDateTimeUtils.toZonedDateTime(456L)})) { - assertEquals(2, v8ValueArray.getLength()); - assertEquals(123L, v8ValueArray.getZonedDateTime(0).toInstant().toEpochMilli()); - assertEquals(456L, v8ValueArray.getZonedDateTime(1).toInstant().toEpochMilli()); - } - // Object[] - try (V8ValueArray v8ValueArray = converter.toV8Value( - v8Runtime, new Object[]{1, "abc"})) { - assertEquals(2, v8ValueArray.getLength()); - assertEquals(1, v8ValueArray.getInteger(0)); - assertEquals("abc", v8ValueArray.getString(1)); - } - } - - @Test - public void testMap() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - try (V8ValueMap v8ValueMap = v8Runtime.createV8ValueMap()) { - v8ValueMap.set("x", "abc"); - assertEquals("abc", v8ValueMap.getString("x")); - JavetEntityMap map = (JavetEntityMap) converter.toObject(v8ValueMap); - assertEquals(1, map.size()); - assertEquals("abc", map.get("x")); - } - try (V8ValueMap v8ValueMap = converter.toV8Value( - v8Runtime, new JavetEntityMap() {{ - put("x", "abc"); - }})) { - assertEquals(1, v8ValueMap.getSize()); - assertEquals("abc", v8ValueMap.getString("x")); - } - } - - @Test - public void testObject() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - try (V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) { - v8ValueObject.set("x", "abc"); - assertEquals("abc", v8ValueObject.getString("x")); - Map map = (Map) converter.toObject(v8ValueObject); - assertTrue(map instanceof HashMap); - assertEquals(1, map.size()); - assertEquals("abc", map.get("x")); - } - try (V8ValueObject v8ValueObject = converter.toV8Value( - v8Runtime, new HashMap() {{ - put("x", "abc"); - }})) { - assertEquals("abc", v8ValueObject.getString("x")); - } - } - - @Test - public void testSet() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - try (V8ValueSet v8ValueSet = v8Runtime.createV8ValueSet()) { - v8ValueSet.add(v8Runtime.createV8ValueString("abc")); - assertTrue(v8ValueSet.has("abc")); - Set set = (Set) converter.toObject(v8ValueSet); - assertEquals(1, set.size()); - assertTrue(set.contains("abc")); - } - try (V8ValueSet v8ValueSet = converter.toV8Value( - v8Runtime, new HashSet(Arrays.asList("a", "b", "c")))) { - assertEquals(3, v8ValueSet.getSize()); - assertTrue(v8ValueSet.has("a")); - assertTrue(v8ValueSet.has("b")); - assertTrue(v8ValueSet.has("c")); - } - } - - @Test - public void testTypedArrayByteArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - byte[] bytes = new byte[]{(byte) 0x01, (byte) 0x02, (byte) 0x03}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, bytes)) { - assertEquals(bytes.length, v8ValueTypedArray.getLength()); - assertEquals(bytes.length, v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(bytes, v8ValueTypedArray.toBytes()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int8Array, bytes.length)) { - assertTrue(v8ValueTypedArray.fromBytes(bytes)); - byte[] newBytes = (byte[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(bytes, newBytes); - } - } - - @Test - public void testTypedArrayDoubleArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - double[] doubles = new double[]{1.23D, 2.34D, 3.45D}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, doubles)) { - assertEquals(doubles.length, v8ValueTypedArray.getLength()); - assertEquals(doubles.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(doubles, v8ValueTypedArray.toDoubles()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Float64Array, doubles.length)) { - assertTrue(v8ValueTypedArray.fromDoubles(doubles)); - double[] newDoubles = (double[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(doubles, newDoubles, 0.001D); - } - } - - @Test - public void testTypedArrayFloatArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - float[] floats = new float[]{1.23F, 2.34F, 3.45F}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, floats)) { - assertEquals(floats.length, v8ValueTypedArray.getLength()); - assertEquals(floats.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(floats, v8ValueTypedArray.toFloats()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Float32Array, floats.length)) { - assertTrue(v8ValueTypedArray.fromFloats(floats)); - float[] newFloats = (float[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(floats, newFloats, 0.001F); - } - } - - @Test - public void testTypedArrayIntegerArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - int[] integers = new int[]{1, 2, 3}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, integers)) { - assertEquals(integers.length, v8ValueTypedArray.getLength()); - assertEquals(integers.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(integers, v8ValueTypedArray.toIntegers()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int32Array, integers.length)) { - assertTrue(v8ValueTypedArray.fromIntegers(integers)); - int[] newIntegers = (int[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(integers, newIntegers); - } - } - - @Test - public void testTypedArrayLongArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - long[] longs = new long[]{1L, 2L, 3L}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, longs)) { - assertEquals(longs.length, v8ValueTypedArray.getLength()); - assertEquals(longs.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(longs, v8ValueTypedArray.toLongs()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.BigInt64Array, longs.length)) { - assertTrue(v8ValueTypedArray.fromLongs(longs)); - long[] newLongs = (long[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(longs, newLongs); - } - } - - @Test - public void testTypedArrayShortArray() throws JavetException { - IJavetConverter converter = new JavetObjectConverter(); - short[] shorts = new short[]{(short) 0x01, (short) 0x02, (short) 0x03}; - try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, shorts)) { - assertEquals(shorts.length, v8ValueTypedArray.getLength()); - assertEquals(shorts.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); - assertEquals(0, v8ValueTypedArray.getByteOffset()); - assertArrayEquals(shorts, v8ValueTypedArray.toShorts()); - } - try (V8ValueTypedArray v8ValueTypedArray = - v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int16Array, shorts.length)) { - assertTrue(v8ValueTypedArray.fromShorts(shorts)); - short[] newShorts = (short[]) converter.toObject(v8ValueTypedArray); - assertArrayEquals(shorts, newShorts); - } - } -} +/* + * 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.converters; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.entities.JavetEntityMap; +import com.caoccao.javet.enums.V8ValueReferenceType; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.utils.JavetDateTimeUtils; +import com.caoccao.javet.values.reference.*; +import org.junit.jupiter.api.Test; + +import java.time.ZonedDateTime; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +@SuppressWarnings("unchecked") +public class TestJavetObjectConverter extends BaseTestJavetRuntime { + @Test + public void testAnonymousFunction() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + Object object = converter.toObject(v8Runtime.getExecutor("const x = {a: 1, b: () => 1}; x;").execute(), true); + assertTrue(object instanceof Map); + Map map = (Map) object; + assertEquals(2, map.size()); + assertEquals(1, map.get("a")); + assertEquals("[Function (anonymous)]", map.get("b")); + } + + @Test + public void testArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + try (V8ValueArray v8ValueArray = v8Runtime.createV8ValueArray()) { + v8ValueArray.push("abc"); + v8ValueArray.push(123); + List list = (List) converter.toObject(v8ValueArray); + assertEquals(2, list.size()); + assertEquals("abc", list.get(0)); + assertEquals(123, list.get(1)); + } + // ArrayList + try (V8ValueArray v8ValueArray = converter.toV8Value( + v8Runtime, Arrays.asList("abc", 123))) { + assertEquals(2, v8ValueArray.getLength()); + assertEquals("abc", v8ValueArray.getString(0)); + assertEquals(123, v8ValueArray.getInteger(1)); + } + // boolean[] + try (V8ValueArray v8ValueArray = converter.toV8Value( + v8Runtime, new boolean[]{true, false})) { + assertEquals(2, v8ValueArray.getLength()); + assertEquals(true, v8ValueArray.getBoolean(0)); + assertEquals(false, v8ValueArray.getBoolean(1)); + } + // String[] + try (V8ValueArray v8ValueArray = converter.toV8Value( + v8Runtime, new String[]{"abc", "def"})) { + assertEquals(2, v8ValueArray.getLength()); + assertEquals("abc", v8ValueArray.getString(0)); + assertEquals("def", v8ValueArray.getString(1)); + } + // ZonedDateTime[] + try (V8ValueArray v8ValueArray = converter.toV8Value( + v8Runtime, new ZonedDateTime[]{ + JavetDateTimeUtils.toZonedDateTime(123L), + JavetDateTimeUtils.toZonedDateTime(456L)})) { + assertEquals(2, v8ValueArray.getLength()); + assertEquals(123L, v8ValueArray.getZonedDateTime(0).toInstant().toEpochMilli()); + assertEquals(456L, v8ValueArray.getZonedDateTime(1).toInstant().toEpochMilli()); + } + // Object[] + try (V8ValueArray v8ValueArray = converter.toV8Value( + v8Runtime, new Object[]{1, "abc"})) { + assertEquals(2, v8ValueArray.getLength()); + assertEquals(1, v8ValueArray.getInteger(0)); + assertEquals("abc", v8ValueArray.getString(1)); + } + } + + @Test + public void testMap() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + try (V8ValueMap v8ValueMap = v8Runtime.createV8ValueMap()) { + v8ValueMap.set("x", "abc"); + assertEquals("abc", v8ValueMap.getString("x")); + JavetEntityMap map = (JavetEntityMap) converter.toObject(v8ValueMap); + assertEquals(1, map.size()); + assertEquals("abc", map.get("x")); + } + try (V8ValueMap v8ValueMap = converter.toV8Value( + v8Runtime, new JavetEntityMap() {{ + put("x", "abc"); + }})) { + assertEquals(1, v8ValueMap.getSize()); + assertEquals("abc", v8ValueMap.getString("x")); + } + } + + @Test + public void testObject() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + try (V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) { + v8ValueObject.set("x", "abc"); + assertEquals("abc", v8ValueObject.getString("x")); + Map map = (Map) converter.toObject(v8ValueObject); + assertTrue(map instanceof HashMap); + assertEquals(1, map.size()); + assertEquals("abc", map.get("x")); + } + try (V8ValueObject v8ValueObject = converter.toV8Value( + v8Runtime, new HashMap() {{ + put("x", "abc"); + }})) { + assertEquals("abc", v8ValueObject.getString("x")); + } + } + + @Test + public void testSet() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + try (V8ValueSet v8ValueSet = v8Runtime.createV8ValueSet()) { + v8ValueSet.add(v8Runtime.createV8ValueString("abc")); + assertTrue(v8ValueSet.has("abc")); + Set set = (Set) converter.toObject(v8ValueSet); + assertEquals(1, set.size()); + assertTrue(set.contains("abc")); + } + try (V8ValueSet v8ValueSet = converter.toV8Value( + v8Runtime, new HashSet(Arrays.asList("a", "b", "c")))) { + assertEquals(3, v8ValueSet.getSize()); + assertTrue(v8ValueSet.has("a")); + assertTrue(v8ValueSet.has("b")); + assertTrue(v8ValueSet.has("c")); + } + } + + @Test + public void testTypedArrayByteArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + byte[] bytes = new byte[]{(byte) 0x01, (byte) 0x02, (byte) 0x03}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, bytes)) { + assertEquals(bytes.length, v8ValueTypedArray.getLength()); + assertEquals(bytes.length, v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(bytes, v8ValueTypedArray.toBytes()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int8Array, bytes.length)) { + assertTrue(v8ValueTypedArray.fromBytes(bytes)); + byte[] newBytes = (byte[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(bytes, newBytes); + } + } + + @Test + public void testTypedArrayDoubleArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + double[] doubles = new double[]{1.23D, 2.34D, 3.45D}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, doubles)) { + assertEquals(doubles.length, v8ValueTypedArray.getLength()); + assertEquals(doubles.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(doubles, v8ValueTypedArray.toDoubles()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Float64Array, doubles.length)) { + assertTrue(v8ValueTypedArray.fromDoubles(doubles)); + double[] newDoubles = (double[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(doubles, newDoubles, 0.001D); + } + } + + @Test + public void testTypedArrayFloatArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + float[] floats = new float[]{1.23F, 2.34F, 3.45F}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, floats)) { + assertEquals(floats.length, v8ValueTypedArray.getLength()); + assertEquals(floats.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(floats, v8ValueTypedArray.toFloats()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Float32Array, floats.length)) { + assertTrue(v8ValueTypedArray.fromFloats(floats)); + float[] newFloats = (float[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(floats, newFloats, 0.001F); + } + } + + @Test + public void testTypedArrayIntegerArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + int[] integers = new int[]{1, 2, 3}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, integers)) { + assertEquals(integers.length, v8ValueTypedArray.getLength()); + assertEquals(integers.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(integers, v8ValueTypedArray.toIntegers()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int32Array, integers.length)) { + assertTrue(v8ValueTypedArray.fromIntegers(integers)); + int[] newIntegers = (int[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(integers, newIntegers); + } + } + + @Test + public void testTypedArrayLongArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + long[] longs = new long[]{1L, 2L, 3L}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, longs)) { + assertEquals(longs.length, v8ValueTypedArray.getLength()); + assertEquals(longs.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(longs, v8ValueTypedArray.toLongs()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.BigInt64Array, longs.length)) { + assertTrue(v8ValueTypedArray.fromLongs(longs)); + long[] newLongs = (long[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(longs, newLongs); + } + } + + @Test + public void testTypedArrayShortArray() throws JavetException { + IJavetConverter converter = new JavetObjectConverter(); + short[] shorts = new short[]{(short) 0x01, (short) 0x02, (short) 0x03}; + try (V8ValueTypedArray v8ValueTypedArray = converter.toV8Value(v8Runtime, shorts)) { + assertEquals(shorts.length, v8ValueTypedArray.getLength()); + assertEquals(shorts.length * v8ValueTypedArray.getSizeInBytes(), v8ValueTypedArray.getByteLength()); + assertEquals(0, v8ValueTypedArray.getByteOffset()); + assertArrayEquals(shorts, v8ValueTypedArray.toShorts()); + } + try (V8ValueTypedArray v8ValueTypedArray = + v8Runtime.createV8ValueTypedArray(V8ValueReferenceType.Int16Array, shorts.length)) { + assertTrue(v8ValueTypedArray.fromShorts(shorts)); + short[] newShorts = (short[]) converter.toObject(v8ValueTypedArray); + assertArrayEquals(shorts, newShorts); + } + } +} diff --git a/src/test/java/com/caoccao/javet/interop/converters/TestJavetPrimitiveConverter.java b/src/test/java/com/caoccao/javet/interop/converters/TestJavetPrimitiveConverter.java index 1ffd64a85..d9dcb98d5 100644 --- a/src/test/java/com/caoccao/javet/interop/converters/TestJavetPrimitiveConverter.java +++ b/src/test/java/com/caoccao/javet/interop/converters/TestJavetPrimitiveConverter.java @@ -1,87 +1,87 @@ -/* - * 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.converters; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.utils.JavetDateTimeUtils; -import com.caoccao.javet.values.primitive.*; -import org.junit.jupiter.api.Test; - -import java.time.ZonedDateTime; - -import static org.junit.jupiter.api.Assertions.*; - -public class TestJavetPrimitiveConverter extends BaseTestJavetRuntime { - protected JavetPrimitiveConverter converter; - - public TestJavetPrimitiveConverter() { - super(); - converter = new JavetPrimitiveConverter(); - } - - @Test - public void testBoolean() throws JavetException { - assertTrue((boolean) converter.toObject(v8Runtime.createV8ValueBoolean(true))); - assertTrue(((V8ValueBoolean) converter.toV8Value(v8Runtime, true)).getValue()); - assertFalse((boolean) converter.toObject(v8Runtime.createV8ValueBoolean(false))); - assertFalse(((V8ValueBoolean) converter.toV8Value(v8Runtime, false)).getValue()); - } - - @Test - public void testDouble() throws JavetException { - assertEquals(1.23D, (double) converter.toObject(v8Runtime.createV8ValueDouble(1.23D)), 0.001); - assertEquals(1.23D, ((V8ValueDouble) converter.toV8Value(v8Runtime, Double.valueOf(1.23D))).getValue(), 0.001); - } - - @Test - public void testFloat() throws JavetException { - assertEquals(1.23F, ((Double) converter.toObject(v8Runtime.createV8ValueDouble(1.23F))).floatValue(), 0.001); - assertEquals(1.23F, ((V8ValueDouble) converter.toV8Value(v8Runtime, Float.valueOf(1.23F))).getValue(), 0.001); - } - - @Test - public void testLong() throws JavetException { - assertEquals(123L, (long) converter.toObject(v8Runtime.createV8ValueLong(123L))); - assertEquals(123L, ((V8ValueLong) converter.toV8Value(v8Runtime, Long.valueOf(123L))).getValue()); - } - - @Test - public void testNull() throws JavetException { - assertNull(converter.toObject(null)); - assertNull(converter.toObject(v8Runtime.createV8ValueNull())); - assertTrue(converter.toV8Value(v8Runtime, null).isNull()); - } - - @Test - public void testString() throws JavetException { - assertEquals("abc", (String) converter.toObject(v8Runtime.createV8ValueString("abc"))); - assertEquals("abc", ((V8ValueString) converter.toV8Value(v8Runtime, "abc")).getValue()); - } - - @Test - public void testUndefined() throws JavetException { - assertNull(converter.toObject(v8Runtime.createV8ValueUndefined())); - } - - @Test - public void testZonedDateTime() throws JavetException { - assertEquals(123L, ((ZonedDateTime) converter.toObject(v8Runtime.createV8ValueZonedDateTime(123L))).toInstant().toEpochMilli()); - assertEquals(123L, ((V8ValueZonedDateTime) converter.toV8Value(v8Runtime, JavetDateTimeUtils.toZonedDateTime(123L))).getValue().toInstant().toEpochMilli()); - } -} +/* + * 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.converters; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.utils.JavetDateTimeUtils; +import com.caoccao.javet.values.primitive.*; +import org.junit.jupiter.api.Test; + +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestJavetPrimitiveConverter extends BaseTestJavetRuntime { + protected JavetPrimitiveConverter converter; + + public TestJavetPrimitiveConverter() { + super(); + converter = new JavetPrimitiveConverter(); + } + + @Test + public void testBoolean() throws JavetException { + assertTrue((boolean) converter.toObject(v8Runtime.createV8ValueBoolean(true))); + assertTrue(((V8ValueBoolean) converter.toV8Value(v8Runtime, true)).getValue()); + assertFalse((boolean) converter.toObject(v8Runtime.createV8ValueBoolean(false))); + assertFalse(((V8ValueBoolean) converter.toV8Value(v8Runtime, false)).getValue()); + } + + @Test + public void testDouble() throws JavetException { + assertEquals(1.23D, (double) converter.toObject(v8Runtime.createV8ValueDouble(1.23D)), 0.001); + assertEquals(1.23D, ((V8ValueDouble) converter.toV8Value(v8Runtime, Double.valueOf(1.23D))).getValue(), 0.001); + } + + @Test + public void testFloat() throws JavetException { + assertEquals(1.23F, ((Double) converter.toObject(v8Runtime.createV8ValueDouble(1.23F))).floatValue(), 0.001); + assertEquals(1.23F, ((V8ValueDouble) converter.toV8Value(v8Runtime, Float.valueOf(1.23F))).getValue(), 0.001); + } + + @Test + public void testLong() throws JavetException { + assertEquals(123L, (long) converter.toObject(v8Runtime.createV8ValueLong(123L))); + assertEquals(123L, ((V8ValueLong) converter.toV8Value(v8Runtime, Long.valueOf(123L))).getValue()); + } + + @Test + public void testNull() throws JavetException { + assertNull(converter.toObject(null)); + assertNull(converter.toObject(v8Runtime.createV8ValueNull())); + assertTrue(converter.toV8Value(v8Runtime, null).isNull()); + } + + @Test + public void testString() throws JavetException { + assertEquals("abc", (String) converter.toObject(v8Runtime.createV8ValueString("abc"))); + assertEquals("abc", ((V8ValueString) converter.toV8Value(v8Runtime, "abc")).getValue()); + } + + @Test + public void testUndefined() throws JavetException { + assertNull(converter.toObject(v8Runtime.createV8ValueUndefined())); + } + + @Test + public void testZonedDateTime() throws JavetException { + assertEquals(123L, ((ZonedDateTime) converter.toObject(v8Runtime.createV8ValueZonedDateTime(123L))).toInstant().toEpochMilli()); + assertEquals(123L, ((V8ValueZonedDateTime) converter.toV8Value(v8Runtime, JavetDateTimeUtils.toZonedDateTime(123L))).getValue().toInstant().toEpochMilli()); + } +} diff --git a/src/test/java/com/caoccao/javet/interop/engine/TestJavetEngineGuard.java b/src/test/java/com/caoccao/javet/interop/engine/TestJavetEngineGuard.java index 235e9b9b2..11a12e4e4 100644 --- a/src/test/java/com/caoccao/javet/interop/engine/TestJavetEngineGuard.java +++ b/src/test/java/com/caoccao/javet/interop/engine/TestJavetEngineGuard.java @@ -1,66 +1,66 @@ -/* - * 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.engine; - -import com.caoccao.javet.BaseTestJavetPool; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.exceptions.JavetTerminatedException; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.utils.JavetDateTimeUtils; -import org.junit.jupiter.api.Test; - -import java.time.Duration; -import java.time.ZonedDateTime; - -import static org.junit.jupiter.api.Assertions.*; - -public class TestJavetEngineGuard extends BaseTestJavetPool { - @Test - public void testTermination() throws JavetException { - // Get an engine from the pool as usual. - try (IJavetEngine iJavetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = iJavetEngine.getV8Runtime(); - // Get a guard from the engine and apply try-with-resource pattern. - try (IJavetEngineGuard iJavetEngineGuard = iJavetEngine.getGuard(1)) { - iJavetEngineGuard.enableInDebugMode(); - v8Runtime.getExecutor("while (true) {}").executeVoid(); - // That infinite loop will be terminated in 10 seconds by the guard. - } catch (JavetTerminatedException e) { - // JavetTerminatedException will be thrown to mark that. - assertFalse(e.isContinuable()); - } - assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger(), - "The V8 runtime is not dead and still be able to execute code afterwards."); - } - } - - @Test - public void testWithoutTermination() throws JavetException { - final long timeoutMillis = 10000; - ZonedDateTime startZonedDateTime = JavetDateTimeUtils.getUTCNow(); - try (IJavetEngine iJavetEngine = javetEnginePool.getEngine()) { - try (IJavetEngineGuard iJavetEngineGuard = iJavetEngine.getGuard(timeoutMillis)) { - V8Runtime v8Runtime = iJavetEngine.getV8Runtime(); - assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); - } - } - ZonedDateTime endZonedDateTime = JavetDateTimeUtils.getUTCNow(); - Duration duration = Duration.between(startZonedDateTime, endZonedDateTime); - assertTrue(duration.toMillis() < timeoutMillis); - } -} +/* + * 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.engine; + +import com.caoccao.javet.BaseTestJavetPool; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.exceptions.JavetTerminatedException; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.utils.JavetDateTimeUtils; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestJavetEngineGuard extends BaseTestJavetPool { + @Test + public void testTermination() throws JavetException { + // Get an engine from the pool as usual. + try (IJavetEngine iJavetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = iJavetEngine.getV8Runtime(); + // Get a guard from the engine and apply try-with-resource pattern. + try (IJavetEngineGuard iJavetEngineGuard = iJavetEngine.getGuard(1)) { + iJavetEngineGuard.enableInDebugMode(); + v8Runtime.getExecutor("while (true) {}").executeVoid(); + // That infinite loop will be terminated in 10 seconds by the guard. + } catch (JavetTerminatedException e) { + // JavetTerminatedException will be thrown to mark that. + assertFalse(e.isContinuable()); + } + assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger(), + "The V8 runtime is not dead and still be able to execute code afterwards."); + } + } + + @Test + public void testWithoutTermination() throws JavetException { + final long timeoutMillis = 10000; + ZonedDateTime startZonedDateTime = JavetDateTimeUtils.getUTCNow(); + try (IJavetEngine iJavetEngine = javetEnginePool.getEngine()) { + try (IJavetEngineGuard iJavetEngineGuard = iJavetEngine.getGuard(timeoutMillis)) { + V8Runtime v8Runtime = iJavetEngine.getV8Runtime(); + assertEquals(2, v8Runtime.getExecutor("1 + 1").executeInteger()); + } + } + ZonedDateTime endZonedDateTime = JavetDateTimeUtils.getUTCNow(); + Duration duration = Duration.between(startZonedDateTime, endZonedDateTime); + assertTrue(duration.toMillis() < timeoutMillis); + } +} diff --git a/src/test/java/com/caoccao/javet/interop/engine/TestPerformance.java b/src/test/java/com/caoccao/javet/interop/engine/TestPerformance.java index 7b63746cc..341614ce9 100644 --- a/src/test/java/com/caoccao/javet/interop/engine/TestPerformance.java +++ b/src/test/java/com/caoccao/javet/interop/engine/TestPerformance.java @@ -1,237 +1,237 @@ -/* - * 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.engine; - -import com.caoccao.javet.BaseTestJavetPool; -import com.caoccao.javet.enums.JSRuntimeType; -import com.caoccao.javet.interop.V8Locker; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.interop.executors.IV8Executor; -import com.caoccao.javet.utils.JavetOSUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class TestPerformance extends BaseTestJavetPool { - public static final String PREFIX_NODE = "Node "; - public static final String PREFIX_V8 = "V8 "; - - private JSRuntimeType jsRuntimeType; - private String prefix; - - @BeforeEach - @Override - public void beforeEach() { - super.beforeEach(); - jsRuntimeType = v8Host.getJSRuntimeType(); - prefix = jsRuntimeType.isNode() ? PREFIX_NODE : PREFIX_V8; - } - - @Test - @Tag("performance") - public void testAdHocContextAnd1Thread() throws Exception { - final int iterations = jsRuntimeType.isNode() ? 200 : 10000; - String codeString = "1 + 1"; - final long startTime = System.currentTimeMillis(); - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int i = 0; i < iterations; i++) { - javetEngine.resetContext(); - assertEquals(2, v8Executor.executeInteger()); - } - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Ad-hoc Context with 1 Thread: {0}", tps); - updateDoc(prefix + "Ad-hoc Context with 1 Thread", tps); - } - - @Test - @Tag("performance") - public void testAdHocContextAnd8Threads() throws Exception { - final int threadCount = 8; - final int iterations = jsRuntimeType.isNode() ? 50 : 5000; - String codeString = "1 + 1"; - Thread[] threads = new Thread[threadCount]; - for (int i = 0; i < threadCount; i++) { - threads[i] = new Thread(() -> { - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int j = 0; j < iterations; j++) { - javetEngine.resetContext(); - assertEquals(2, v8Executor.executeInteger()); - } - } catch (Exception e) { - logger.logError(e, "Failed to execute."); - } - }); - } - final long startTime = System.currentTimeMillis(); - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - thread.join(); - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Ad-hoc Context with 8 Threads: {0}", tps); - updateDoc(prefix + "Ad-hoc Context with 8 Threads", tps); - } - - @Test - @Tag("performance") - public void testAdHocIsolateAnd1Thread() throws Exception { - final int iterations = jsRuntimeType.isNode() ? 200 : 10000; - String codeString = "1 + 1"; - final long startTime = System.currentTimeMillis(); - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int i = 0; i < iterations; i++) { - javetEngine.resetIsolate(); - assertEquals(2, v8Executor.executeInteger()); - } - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Ad-hoc Isolate with 1 Thread: {0}", tps); - updateDoc(prefix + "Ad-hoc Isolate with 1 Thread", tps); - } - - @Test - @Tag("performance") - public void testAdHocIsolateAnd8Threads() throws Exception { - final int threadCount = 8; - final int iterations = jsRuntimeType.isNode() ? 50 : 5000; - String codeString = "1 + 1"; - Thread[] threads = new Thread[threadCount]; - for (int i = 0; i < threadCount; i++) { - threads[i] = new Thread(() -> { - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int j = 0; j < iterations; j++) { - javetEngine.resetIsolate(); - assertEquals(2, v8Executor.executeInteger()); - } - } catch (Exception e) { - logger.logError(e, "Failed to execute."); - } - }); - } - final long startTime = System.currentTimeMillis(); - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - thread.join(); - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Ad-hoc Isolate with 8 Threads: {0}", tps); - updateDoc(prefix + "Ad-hoc Isolate with 8 Threads", tps); - } - - @Test - @Tag("performance") - public void testSingleContextAnd1Thread() throws Exception { - final int iterations = 2000000; - String codeString = "1 + 1"; - final long startTime = System.currentTimeMillis(); - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - try (V8Locker v8Locker = v8Runtime.getV8Locker()) { - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int i = 0; i < iterations; i++) { - assertEquals(2, v8Executor.executeInteger()); - } - } - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Single Context with 1 Thread: {0}", tps); - updateDoc(prefix + "Single Context with 1 Thread", tps); - } - - @Test - @Tag("performance") - public void testSingleContextAnd8Threads() throws Exception { - final int threadCount = 8; - final int iterations = 1000000; - String codeString = "1 + 1"; - Thread[] threads = new Thread[threadCount]; - for (int i = 0; i < threadCount; i++) { - threads[i] = new Thread(() -> { - try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { - V8Runtime v8Runtime = javetEngine.getV8Runtime(); - try (V8Locker v8Locker = v8Runtime.getV8Locker()) { - IV8Executor v8Executor = v8Runtime.getExecutor(codeString); - for (int j = 0; j < iterations; j++) { - assertEquals(2, v8Executor.executeInteger()); - } - } - } catch (Exception e) { - logger.logError(e, "Failed to execute."); - } - }); - } - final long startTime = System.currentTimeMillis(); - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - thread.join(); - } - final long stopTime = System.currentTimeMillis(); - final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); - logger.logInfo(prefix + "Single Context with 8 Threads: {0}", tps); - updateDoc(prefix + "Single Context with 8 Threads", tps); - } - - protected void updateDoc(String prefix, long tps) throws IOException { - DecimalFormat decimalFormat = new DecimalFormat("#,###"); - File docFile = new File( - JavetOSUtils.WORKING_DIRECTORY, - "docs/reference/performance.rst"); - List lines = new ArrayList<>(); - for (String line : Files.readAllLines(docFile.toPath(), StandardCharsets.UTF_8)) { - if (line.startsWith(prefix)) { - line = line.substring(0, line.lastIndexOf(" ") + 1) + decimalFormat.format(tps); - } - lines.add(line); - } - lines.add(""); - try (FileWriter fileWriter = new FileWriter(docFile, false)) { - fileWriter.write(String.join("\n", lines)); - } - } -} +/* + * 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.engine; + +import com.caoccao.javet.BaseTestJavetPool; +import com.caoccao.javet.enums.JSRuntimeType; +import com.caoccao.javet.interop.V8Locker; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.interop.executors.IV8Executor; +import com.caoccao.javet.utils.JavetOSUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestPerformance extends BaseTestJavetPool { + public static final String PREFIX_NODE = "Node "; + public static final String PREFIX_V8 = "V8 "; + + private JSRuntimeType jsRuntimeType; + private String prefix; + + @BeforeEach + @Override + public void beforeEach() { + super.beforeEach(); + jsRuntimeType = v8Host.getJSRuntimeType(); + prefix = jsRuntimeType.isNode() ? PREFIX_NODE : PREFIX_V8; + } + + @Test + @Tag("performance") + public void testAdHocContextAnd1Thread() throws Exception { + final int iterations = jsRuntimeType.isNode() ? 200 : 10000; + String codeString = "1 + 1"; + final long startTime = System.currentTimeMillis(); + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int i = 0; i < iterations; i++) { + javetEngine.resetContext(); + assertEquals(2, v8Executor.executeInteger()); + } + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Ad-hoc Context with 1 Thread: {0}", tps); + updateDoc(prefix + "Ad-hoc Context with 1 Thread", tps); + } + + @Test + @Tag("performance") + public void testAdHocContextAnd8Threads() throws Exception { + final int threadCount = 8; + final int iterations = jsRuntimeType.isNode() ? 50 : 5000; + String codeString = "1 + 1"; + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = new Thread(() -> { + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int j = 0; j < iterations; j++) { + javetEngine.resetContext(); + assertEquals(2, v8Executor.executeInteger()); + } + } catch (Exception e) { + logger.logError(e, "Failed to execute."); + } + }); + } + final long startTime = System.currentTimeMillis(); + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Ad-hoc Context with 8 Threads: {0}", tps); + updateDoc(prefix + "Ad-hoc Context with 8 Threads", tps); + } + + @Test + @Tag("performance") + public void testAdHocIsolateAnd1Thread() throws Exception { + final int iterations = jsRuntimeType.isNode() ? 200 : 10000; + String codeString = "1 + 1"; + final long startTime = System.currentTimeMillis(); + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int i = 0; i < iterations; i++) { + javetEngine.resetIsolate(); + assertEquals(2, v8Executor.executeInteger()); + } + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Ad-hoc Isolate with 1 Thread: {0}", tps); + updateDoc(prefix + "Ad-hoc Isolate with 1 Thread", tps); + } + + @Test + @Tag("performance") + public void testAdHocIsolateAnd8Threads() throws Exception { + final int threadCount = 8; + final int iterations = jsRuntimeType.isNode() ? 50 : 5000; + String codeString = "1 + 1"; + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = new Thread(() -> { + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int j = 0; j < iterations; j++) { + javetEngine.resetIsolate(); + assertEquals(2, v8Executor.executeInteger()); + } + } catch (Exception e) { + logger.logError(e, "Failed to execute."); + } + }); + } + final long startTime = System.currentTimeMillis(); + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Ad-hoc Isolate with 8 Threads: {0}", tps); + updateDoc(prefix + "Ad-hoc Isolate with 8 Threads", tps); + } + + @Test + @Tag("performance") + public void testSingleContextAnd1Thread() throws Exception { + final int iterations = 2000000; + String codeString = "1 + 1"; + final long startTime = System.currentTimeMillis(); + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + try (V8Locker v8Locker = v8Runtime.getV8Locker()) { + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int i = 0; i < iterations; i++) { + assertEquals(2, v8Executor.executeInteger()); + } + } + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Single Context with 1 Thread: {0}", tps); + updateDoc(prefix + "Single Context with 1 Thread", tps); + } + + @Test + @Tag("performance") + public void testSingleContextAnd8Threads() throws Exception { + final int threadCount = 8; + final int iterations = 1000000; + String codeString = "1 + 1"; + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = new Thread(() -> { + try (IJavetEngine javetEngine = javetEnginePool.getEngine()) { + V8Runtime v8Runtime = javetEngine.getV8Runtime(); + try (V8Locker v8Locker = v8Runtime.getV8Locker()) { + IV8Executor v8Executor = v8Runtime.getExecutor(codeString); + for (int j = 0; j < iterations; j++) { + assertEquals(2, v8Executor.executeInteger()); + } + } + } catch (Exception e) { + logger.logError(e, "Failed to execute."); + } + }); + } + final long startTime = System.currentTimeMillis(); + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + final long stopTime = System.currentTimeMillis(); + final long tps = iterations * (long) threadCount * 1000 / (stopTime - startTime); + logger.logInfo(prefix + "Single Context with 8 Threads: {0}", tps); + updateDoc(prefix + "Single Context with 8 Threads", tps); + } + + protected void updateDoc(String prefix, long tps) throws IOException { + DecimalFormat decimalFormat = new DecimalFormat("#,###"); + File docFile = new File( + JavetOSUtils.WORKING_DIRECTORY, + "docs/reference/performance.rst"); + List lines = new ArrayList<>(); + for (String line : Files.readAllLines(docFile.toPath(), StandardCharsets.UTF_8)) { + if (line.startsWith(prefix)) { + line = line.substring(0, line.lastIndexOf(" ") + 1) + decimalFormat.format(tps); + } + lines.add(line); + } + lines.add(""); + try (FileWriter fileWriter = new FileWriter(docFile, false)) { + fileWriter.write(String.join("\n", lines)); + } + } +} diff --git a/src/test/java/com/caoccao/javet/mock/MockAnnotationBasedCallbackReceiver.java b/src/test/java/com/caoccao/javet/mock/MockAnnotationBasedCallbackReceiver.java index 944e43134..58e48028e 100644 --- a/src/test/java/com/caoccao/javet/mock/MockAnnotationBasedCallbackReceiver.java +++ b/src/test/java/com/caoccao/javet/mock/MockAnnotationBasedCallbackReceiver.java @@ -1,195 +1,195 @@ -/* - * 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.mock; - -import com.caoccao.javet.annotations.V8Function; -import com.caoccao.javet.annotations.V8Property; -import com.caoccao.javet.annotations.V8RuntimeSetter; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.values.reference.V8ValueArray; -import com.caoccao.javet.values.reference.V8ValueFunction; -import com.caoccao.javet.values.reference.V8ValueObject; - -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MockAnnotationBasedCallbackReceiver { - private AtomicInteger count; - private String stringValue; - private V8Runtime v8Runtime; - - public MockAnnotationBasedCallbackReceiver() { - count = new AtomicInteger(0); - stringValue = null; - v8Runtime = null; - } - - // Static method. - @V8Function(name = "staticEcho") - public static String staticEcho(String str) { - return str; - } - - @V8Function - public Integer contextScope(V8ValueFunction v8ValueFunction) throws JavetException { - assertTrue(v8ValueFunction.getJSFunctionType().isUserDefined()); - assertTrue(v8ValueFunction.getJSScopeType().isFunction()); - if (v8ValueFunction.setSourceCode("() => a + 2")) { - assertTrue(v8ValueFunction.getJSScopeType().isFunction()); - return v8ValueFunction.callInteger(null); - } else { - return 0; - } - } - - // Instance method with same name and same signature. - @V8Function(name = "echo") - public String echo(String str) { - count.incrementAndGet(); - return str; - } - - // Instance method with converter for non-primitive objects. - @V8Function(name = "generateArrayWithConverter") - public Object[] generateArrayWithConverter() throws JavetException { - count.incrementAndGet(); - // Converter is able to recognize non-primitive types. - return new Object[]{"a", 1}; - } - - // Instance method requiring V8Runtime without converter. - @V8Function - public V8ValueArray generateArrayWithoutConverter() throws JavetException { - count.incrementAndGet(); - V8ValueArray v8ValueArray = v8Runtime.createV8ValueArray(); - v8ValueArray.push("a"); - v8ValueArray.push(1); - return v8ValueArray; - } - - public int getCount() { - return count.get(); - } - - @V8Property - public Integer getIntegerValue() { - count.incrementAndGet(); - return 123; - } - - @V8Property - public String getStringValue() { - count.incrementAndGet(); - return stringValue; - } - - @V8Property(thisObjectRequired = true) - public String getStringValueWithThis(V8ValueObject thisObject) throws JavetException { - count.incrementAndGet(); - return thisObject.getString("stringValue"); - } - - // Instance method with different name and same signature. - @V8Function(name = "add") - public Integer mathAdd(Integer a, Integer b) { - count.incrementAndGet(); - return a + b; - } - - // Instance method with primitive type byte - @V8Function(name = "primitiveAddByte") - public byte primitiveAddByte(byte a, byte b) { - count.incrementAndGet(); - return (byte) (a + b); - } - - // Instance method with primitive type double - @V8Function(name = "primitiveAddDouble") - public double primitiveAddDouble(double a, double b) { - count.incrementAndGet(); - return a + b; - } - - // Instance method with primitive type float - @V8Function(name = "primitiveAddFloat") - public float primitiveAddFloat(float a, float b) { - count.incrementAndGet(); - return a + b; - } - - // Instance method with primitive type int - @V8Function(name = "primitiveAddInt") - public int primitiveAddInt(int a, int b) { - count.incrementAndGet(); - return a + b; - } - - // Instance method with primitive type long - @V8Function(name = "primitiveAddLong") - public long primitiveAddLong(long a, long b) { - count.incrementAndGet(); - return a + b; - } - - // Instance method with primitive type short - @V8Function(name = "primitiveAddShort") - public short primitiveAddShort(short a, short b) { - count.incrementAndGet(); - return Integer.valueOf(a + b).shortValue(); - } - - // Instance method with primitive type char - @V8Function(name = "primitiveIncreaseChar") - public char primitiveIncreaseChar(char c) { - count.incrementAndGet(); - return (char) ((int) c + 1); - } - - // Instance method with primitive type boolean - @V8Function(name = "primitiveRevertBoolean") - public boolean primitiveRevertBoolean(boolean b) { - count.incrementAndGet(); - return !b; - } - - @V8Function(thisObjectRequired = true) - public V8ValueObject self(V8ValueObject thisObject) { - count.incrementAndGet(); - return thisObject; - } - - @V8Property - public void setStringValue(String stringValue) { - count.incrementAndGet(); - this.stringValue = stringValue; - } - - @V8Property(thisObjectRequired = true) - public void setStringValueWithThis(V8ValueObject thisObject, String stringValue) throws JavetException { - count.incrementAndGet(); - thisObject.set("stringValue", stringValue); - } - - // Declare the V8RuntimeSetter for dependency injection. - @V8RuntimeSetter - public void setV8Runtime(V8Runtime v8Runtime) { - this.v8Runtime = v8Runtime; - } -} +/* + * 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.mock; + +import com.caoccao.javet.annotations.V8Function; +import com.caoccao.javet.annotations.V8Property; +import com.caoccao.javet.annotations.V8RuntimeSetter; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.values.reference.V8ValueArray; +import com.caoccao.javet.values.reference.V8ValueFunction; +import com.caoccao.javet.values.reference.V8ValueObject; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MockAnnotationBasedCallbackReceiver { + private AtomicInteger count; + private String stringValue; + private V8Runtime v8Runtime; + + public MockAnnotationBasedCallbackReceiver() { + count = new AtomicInteger(0); + stringValue = null; + v8Runtime = null; + } + + // Static method. + @V8Function(name = "staticEcho") + public static String staticEcho(String str) { + return str; + } + + @V8Function + public Integer contextScope(V8ValueFunction v8ValueFunction) throws JavetException { + assertTrue(v8ValueFunction.getJSFunctionType().isUserDefined()); + assertTrue(v8ValueFunction.getJSScopeType().isFunction()); + if (v8ValueFunction.setSourceCode("() => a + 2")) { + assertTrue(v8ValueFunction.getJSScopeType().isFunction()); + return v8ValueFunction.callInteger(null); + } else { + return 0; + } + } + + // Instance method with same name and same signature. + @V8Function(name = "echo") + public String echo(String str) { + count.incrementAndGet(); + return str; + } + + // Instance method with converter for non-primitive objects. + @V8Function(name = "generateArrayWithConverter") + public Object[] generateArrayWithConverter() throws JavetException { + count.incrementAndGet(); + // Converter is able to recognize non-primitive types. + return new Object[]{"a", 1}; + } + + // Instance method requiring V8Runtime without converter. + @V8Function + public V8ValueArray generateArrayWithoutConverter() throws JavetException { + count.incrementAndGet(); + V8ValueArray v8ValueArray = v8Runtime.createV8ValueArray(); + v8ValueArray.push("a"); + v8ValueArray.push(1); + return v8ValueArray; + } + + public int getCount() { + return count.get(); + } + + @V8Property + public Integer getIntegerValue() { + count.incrementAndGet(); + return 123; + } + + @V8Property + public String getStringValue() { + count.incrementAndGet(); + return stringValue; + } + + @V8Property(thisObjectRequired = true) + public String getStringValueWithThis(V8ValueObject thisObject) throws JavetException { + count.incrementAndGet(); + return thisObject.getString("stringValue"); + } + + // Instance method with different name and same signature. + @V8Function(name = "add") + public Integer mathAdd(Integer a, Integer b) { + count.incrementAndGet(); + return a + b; + } + + // Instance method with primitive type byte + @V8Function(name = "primitiveAddByte") + public byte primitiveAddByte(byte a, byte b) { + count.incrementAndGet(); + return (byte) (a + b); + } + + // Instance method with primitive type double + @V8Function(name = "primitiveAddDouble") + public double primitiveAddDouble(double a, double b) { + count.incrementAndGet(); + return a + b; + } + + // Instance method with primitive type float + @V8Function(name = "primitiveAddFloat") + public float primitiveAddFloat(float a, float b) { + count.incrementAndGet(); + return a + b; + } + + // Instance method with primitive type int + @V8Function(name = "primitiveAddInt") + public int primitiveAddInt(int a, int b) { + count.incrementAndGet(); + return a + b; + } + + // Instance method with primitive type long + @V8Function(name = "primitiveAddLong") + public long primitiveAddLong(long a, long b) { + count.incrementAndGet(); + return a + b; + } + + // Instance method with primitive type short + @V8Function(name = "primitiveAddShort") + public short primitiveAddShort(short a, short b) { + count.incrementAndGet(); + return Integer.valueOf(a + b).shortValue(); + } + + // Instance method with primitive type char + @V8Function(name = "primitiveIncreaseChar") + public char primitiveIncreaseChar(char c) { + count.incrementAndGet(); + return (char) ((int) c + 1); + } + + // Instance method with primitive type boolean + @V8Function(name = "primitiveRevertBoolean") + public boolean primitiveRevertBoolean(boolean b) { + count.incrementAndGet(); + return !b; + } + + @V8Function(thisObjectRequired = true) + public V8ValueObject self(V8ValueObject thisObject) { + count.incrementAndGet(); + return thisObject; + } + + @V8Property + public void setStringValue(String stringValue) { + count.incrementAndGet(); + this.stringValue = stringValue; + } + + @V8Property(thisObjectRequired = true) + public void setStringValueWithThis(V8ValueObject thisObject, String stringValue) throws JavetException { + count.incrementAndGet(); + thisObject.set("stringValue", stringValue); + } + + // Declare the V8RuntimeSetter for dependency injection. + @V8RuntimeSetter + public void setV8Runtime(V8Runtime v8Runtime) { + this.v8Runtime = v8Runtime; + } +} diff --git a/src/test/java/com/caoccao/javet/tutorial/TestInterception.java b/src/test/java/com/caoccao/javet/tutorial/TestInterception.java index 08060df02..783894560 100644 --- a/src/test/java/com/caoccao/javet/tutorial/TestInterception.java +++ b/src/test/java/com/caoccao/javet/tutorial/TestInterception.java @@ -1,107 +1,107 @@ -/* - * 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.tutorial; - -import com.caoccao.javet.annotations.V8Function; -import com.caoccao.javet.annotations.V8Property; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interception.logging.JavetStandardConsoleInterceptor; -import com.caoccao.javet.interop.V8Host; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.values.reference.V8ValueObject; - -public class TestInterception { - private String name; - private int value; - - public static void main(String[] args) throws JavetException { - // Step 1: Create a V8 runtime from V8 host in try-with-resource. - try (V8Runtime v8Runtime = V8Host.getV8Instance().createV8Runtime()) { - // Step 2: Register console. - JavetStandardConsoleInterceptor javetStandardConsoleInterceptor = new JavetStandardConsoleInterceptor(v8Runtime); - javetStandardConsoleInterceptor.register(v8Runtime.getGlobalObject()); - // Step 3: Create an interceptor. - TestInterception testInterceptor = new TestInterception(); - // Step 4: Bind the interceptor to a variable. - try (V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) { - v8Runtime.getGlobalObject().set("a", v8ValueObject); - v8ValueObject.bind(testInterceptor); - } - - // Test property name - v8Runtime.getExecutor("console.log(`a.name is initially ${a.name}.`);").executeVoid(); // null - // a.name setter => setName(String name) - v8Runtime.getExecutor("a.name = 'Javet';").executeVoid(); - // name is changed - System.out.println("Interceptor name is " + testInterceptor.getName() + "."); // Javet - // a.name getter => getName() - v8Runtime.getExecutor("console.log(`a.name is now ${a.name}.`);").executeVoid(); // Javet - - // Test property value - v8Runtime.getExecutor("console.log(`a.value is initially ${a.value}.`);").executeVoid(); // 0 - // a.value setter => setValue(String value) - v8Runtime.getExecutor("a.value = 123;").executeVoid(); - // value is changed - System.out.println("Interceptor value is " + testInterceptor.getValue() + "."); // 123 - // a.value getter => getValue() - v8Runtime.getExecutor("console.log(`a.value is now ${a.value}.`);").executeVoid(); // 123 - - // Test functions - v8Runtime.getExecutor("console.log(`a.increaseAndGet() is ${a.increaseAndGet()}.`);").executeVoid(); // 124 - v8Runtime.getExecutor("console.log(`a.add(76) is ${a.add(76)}.`);").executeVoid(); // 200 - - // Step 5: Delete the interceptor. - v8Runtime.getGlobalObject().delete("a"); - // Step 6: Unregister console. - javetStandardConsoleInterceptor.unregister(v8Runtime.getGlobalObject()); - // Step 7: Notify V8 to perform GC. (Optional) - v8Runtime.lowMemoryNotification(); - } - } - - @V8Function - public int add(int delta) { - value += delta; - return value; - } - - @V8Property - public String getName() { - return name; - } - - @V8Property - public int getValue() { - return value; - } - - @V8Function - public int increaseAndGet() { - return ++value; - } - - @V8Property - public void setName(String name) { - this.name = name; - } - - @V8Property - public void setValue(int value) { - this.value = value; - } -} +/* + * 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.tutorial; + +import com.caoccao.javet.annotations.V8Function; +import com.caoccao.javet.annotations.V8Property; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interception.logging.JavetStandardConsoleInterceptor; +import com.caoccao.javet.interop.V8Host; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.values.reference.V8ValueObject; + +public class TestInterception { + private String name; + private int value; + + public static void main(String[] args) throws JavetException { + // Step 1: Create a V8 runtime from V8 host in try-with-resource. + try (V8Runtime v8Runtime = V8Host.getV8Instance().createV8Runtime()) { + // Step 2: Register console. + JavetStandardConsoleInterceptor javetStandardConsoleInterceptor = new JavetStandardConsoleInterceptor(v8Runtime); + javetStandardConsoleInterceptor.register(v8Runtime.getGlobalObject()); + // Step 3: Create an interceptor. + TestInterception testInterceptor = new TestInterception(); + // Step 4: Bind the interceptor to a variable. + try (V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) { + v8Runtime.getGlobalObject().set("a", v8ValueObject); + v8ValueObject.bind(testInterceptor); + } + + // Test property name + v8Runtime.getExecutor("console.log(`a.name is initially ${a.name}.`);").executeVoid(); // null + // a.name setter => setName(String name) + v8Runtime.getExecutor("a.name = 'Javet';").executeVoid(); + // name is changed + System.out.println("Interceptor name is " + testInterceptor.getName() + "."); // Javet + // a.name getter => getName() + v8Runtime.getExecutor("console.log(`a.name is now ${a.name}.`);").executeVoid(); // Javet + + // Test property value + v8Runtime.getExecutor("console.log(`a.value is initially ${a.value}.`);").executeVoid(); // 0 + // a.value setter => setValue(String value) + v8Runtime.getExecutor("a.value = 123;").executeVoid(); + // value is changed + System.out.println("Interceptor value is " + testInterceptor.getValue() + "."); // 123 + // a.value getter => getValue() + v8Runtime.getExecutor("console.log(`a.value is now ${a.value}.`);").executeVoid(); // 123 + + // Test functions + v8Runtime.getExecutor("console.log(`a.increaseAndGet() is ${a.increaseAndGet()}.`);").executeVoid(); // 124 + v8Runtime.getExecutor("console.log(`a.add(76) is ${a.add(76)}.`);").executeVoid(); // 200 + + // Step 5: Delete the interceptor. + v8Runtime.getGlobalObject().delete("a"); + // Step 6: Unregister console. + javetStandardConsoleInterceptor.unregister(v8Runtime.getGlobalObject()); + // Step 7: Notify V8 to perform GC. (Optional) + v8Runtime.lowMemoryNotification(); + } + } + + @V8Function + public int add(int delta) { + value += delta; + return value; + } + + @V8Property + public String getName() { + return name; + } + + @V8Property + public int getValue() { + return value; + } + + @V8Function + public int increaseAndGet() { + return ++value; + } + + @V8Property + public void setName(String name) { + this.name = name; + } + + @V8Property + public void setValue(int value) { + this.value = value; + } +} diff --git a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTConfig.java b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTConfig.java index 7220995ac..1a34f2f97 100644 --- a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTConfig.java +++ b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTConfig.java @@ -1,56 +1,56 @@ -/* - * 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.tutorial.cdt; - -import com.caoccao.javet.interop.V8Runtime; - -public final class CDTConfig { - public static final String COMMAND_EXIT = ".exit"; - public static final String PATH_ROOT = "/"; - public static final String PATH_JSON = "/json"; - public static final String PATH_JSON_VERSION = "/json/version"; - public static final String PATH_JAVET = "/javet"; - private static int port = 0; - private static V8Runtime v8Runtime = null; - private static String webSocketUrl = null; - - static { - setPort(9229); - } - - public static int getPort() { - return port; - } - - public static V8Runtime getV8Runtime() { - return v8Runtime; - } - - public static String getWebSocketUrl() { - return webSocketUrl; - } - - public static void setPort(int port) { - CDTConfig.port = port; - webSocketUrl = "ws://127.0.0.1:" + Integer.toString(port) + PATH_JAVET; - } - - public static void setV8Runtime(V8Runtime v8Runtime) { - CDTConfig.v8Runtime = v8Runtime; - } -} +/* + * 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.tutorial.cdt; + +import com.caoccao.javet.interop.V8Runtime; + +public final class CDTConfig { + public static final String COMMAND_EXIT = ".exit"; + public static final String PATH_ROOT = "/"; + public static final String PATH_JSON = "/json"; + public static final String PATH_JSON_VERSION = "/json/version"; + public static final String PATH_JAVET = "/javet"; + private static int port = 0; + private static V8Runtime v8Runtime = null; + private static String webSocketUrl = null; + + static { + setPort(9229); + } + + public static int getPort() { + return port; + } + + public static V8Runtime getV8Runtime() { + return v8Runtime; + } + + public static String getWebSocketUrl() { + return webSocketUrl; + } + + public static void setPort(int port) { + CDTConfig.port = port; + webSocketUrl = "ws://127.0.0.1:" + Integer.toString(port) + PATH_JAVET; + } + + public static void setV8Runtime(V8Runtime v8Runtime) { + CDTConfig.v8Runtime = v8Runtime; + } +} diff --git a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTHttpServlet.java b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTHttpServlet.java index 55376998a..492716283 100644 --- a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTHttpServlet.java +++ b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTHttpServlet.java @@ -1,63 +1,63 @@ -/* - * 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.tutorial.cdt; - -import com.caoccao.javet.interfaces.IJavetLogger; -import com.caoccao.javet.utils.JavetDefaultLogger; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public class CDTHttpServlet extends HttpServlet { - public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json; charset=UTF-8"; - protected IJavetLogger logger; - - public CDTHttpServlet() { - this.logger = new JavetDefaultLogger(getClass().getName()); - } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String requestURI = request.getRequestURI(); - response.setContentType(APPLICATION_JSON_CHARSET_UTF_8); - response.setStatus(HttpServletResponse.SC_OK); - if (CDTConfig.PATH_JSON.equals(requestURI)) { - response.getWriter().println("[ {\n" + - " \"description\": \"javet\",\n" + - " \"devtoolsFrontendUrl\": \"devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&" + CDTConfig.getWebSocketUrl() + "\",\n" + - " \"devtoolsFrontendUrlCompat\": \"devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&" + CDTConfig.getWebSocketUrl() + "\",\n" + - " \"id\": \"javet\",\n" + - " \"title\": \"javet\",\n" + - " \"type\": \"node\",\n" + // Type must be node - " \"url\": \"file://\",\n" + - " \"webSocketDebuggerUrl\": \"" + CDTConfig.getWebSocketUrl() + "\"\n" + - "} ]\n"); - } else if (CDTConfig.PATH_JSON_VERSION.equals(requestURI)) { - response.getWriter().println("{\n" + - " \"Browser\": \"Javet\",\n" + - " \"Protocol-Version\": \"1.3\"\n" + - "} \n"); - } else { - response.getWriter().println("{}"); - } - } -} +/* + * 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.tutorial.cdt; + +import com.caoccao.javet.interfaces.IJavetLogger; +import com.caoccao.javet.utils.JavetDefaultLogger; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class CDTHttpServlet extends HttpServlet { + public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json; charset=UTF-8"; + protected IJavetLogger logger; + + public CDTHttpServlet() { + this.logger = new JavetDefaultLogger(getClass().getName()); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String requestURI = request.getRequestURI(); + response.setContentType(APPLICATION_JSON_CHARSET_UTF_8); + response.setStatus(HttpServletResponse.SC_OK); + if (CDTConfig.PATH_JSON.equals(requestURI)) { + response.getWriter().println("[ {\n" + + " \"description\": \"javet\",\n" + + " \"devtoolsFrontendUrl\": \"devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&" + CDTConfig.getWebSocketUrl() + "\",\n" + + " \"devtoolsFrontendUrlCompat\": \"devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&" + CDTConfig.getWebSocketUrl() + "\",\n" + + " \"id\": \"javet\",\n" + + " \"title\": \"javet\",\n" + + " \"type\": \"node\",\n" + // Type must be node + " \"url\": \"file://\",\n" + + " \"webSocketDebuggerUrl\": \"" + CDTConfig.getWebSocketUrl() + "\"\n" + + "} ]\n"); + } else if (CDTConfig.PATH_JSON_VERSION.equals(requestURI)) { + response.getWriter().println("{\n" + + " \"Browser\": \"Javet\",\n" + + " \"Protocol-Version\": \"1.3\"\n" + + "} \n"); + } else { + response.getWriter().println("{}"); + } + } +} diff --git a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTShell.java b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTShell.java index 9a0a7d82c..53be01fe8 100644 --- a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTShell.java +++ b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTShell.java @@ -1,95 +1,95 @@ -/* - * 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.tutorial.cdt; - -import com.caoccao.javet.interfaces.IJavetLogger; -import com.caoccao.javet.interop.V8Host; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.utils.JavetDefaultLogger; -import com.caoccao.javet.values.V8Value; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer; -import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter; - -import java.util.Scanner; - -public class CDTShell { - protected IJavetLogger logger; - - public CDTShell() { - logger = new JavetDefaultLogger(getClass().getName()); - } - - public void run() { - Server jsonServer = new Server(CDTConfig.getPort()); - ServletContextHandler jsonServletContextHandler = new ServletContextHandler( - ServletContextHandler.SESSIONS | ServletContextHandler.NO_SECURITY); - jsonServletContextHandler.setContextPath(CDTConfig.PATH_ROOT); - jsonServer.setHandler(jsonServletContextHandler); - try { - jsonServletContextHandler.addServlet(CDTHttpServlet.class, CDTConfig.PATH_JSON); - jsonServletContextHandler.addServlet(CDTHttpServlet.class, CDTConfig.PATH_JSON_VERSION); - NativeWebSocketServletContainerInitializer.configure(jsonServletContextHandler, - (servletContext, nativeWebSocketConfiguration) -> { - nativeWebSocketConfiguration.getPolicy().setMaxTextMessageBufferSize(0xFFFFFF); - nativeWebSocketConfiguration.addMapping(CDTConfig.PATH_JAVET, CDTWebSocketAdapter.class); - }); - WebSocketUpgradeFilter.configure(jsonServletContextHandler); - try (V8Runtime v8Runtime = V8Host.getV8Instance().createV8Runtime()) { - jsonServer.start(); - logger.logInfo("Server is started. Please press any key to stop the server."); - System.out.println("Welcome to CDT Shell!"); - System.out.println("Input the script or '" + CDTConfig.COMMAND_EXIT + "' to exit."); - CDTConfig.setV8Runtime(v8Runtime); - try (Scanner scanner = new Scanner(System.in)) { - while (true) { - System.out.print("> "); - String command = scanner.nextLine(); - if (CDTConfig.COMMAND_EXIT.equals(command)) { - break; - } - try (V8Value v8Value = v8Runtime.getExecutor(command).execute()) { - if (v8Value != null) { - System.out.println(v8Value.toString()); - } - } catch (Throwable t) { - System.err.println(t.getMessage()); - } - } - } - } finally { - CDTConfig.setV8Runtime(null); - } - } catch (Throwable t) { - logger.logError(t, t.getMessage()); - } finally { - if (jsonServer.isStarted() || jsonServer.isStarting()) { - logger.logInfo("Server is being stopped."); - try { - jsonServer.stop(); - } catch (Throwable t) { - logger.logError(t, t.getMessage()); - } - logger.logInfo("Server is stopped."); - } - } - - } - -} +/* + * 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.tutorial.cdt; + +import com.caoccao.javet.interfaces.IJavetLogger; +import com.caoccao.javet.interop.V8Host; +import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.utils.JavetDefaultLogger; +import com.caoccao.javet.values.V8Value; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer; +import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter; + +import java.util.Scanner; + +public class CDTShell { + protected IJavetLogger logger; + + public CDTShell() { + logger = new JavetDefaultLogger(getClass().getName()); + } + + public void run() { + Server jsonServer = new Server(CDTConfig.getPort()); + ServletContextHandler jsonServletContextHandler = new ServletContextHandler( + ServletContextHandler.SESSIONS | ServletContextHandler.NO_SECURITY); + jsonServletContextHandler.setContextPath(CDTConfig.PATH_ROOT); + jsonServer.setHandler(jsonServletContextHandler); + try { + jsonServletContextHandler.addServlet(CDTHttpServlet.class, CDTConfig.PATH_JSON); + jsonServletContextHandler.addServlet(CDTHttpServlet.class, CDTConfig.PATH_JSON_VERSION); + NativeWebSocketServletContainerInitializer.configure(jsonServletContextHandler, + (servletContext, nativeWebSocketConfiguration) -> { + nativeWebSocketConfiguration.getPolicy().setMaxTextMessageBufferSize(0xFFFFFF); + nativeWebSocketConfiguration.addMapping(CDTConfig.PATH_JAVET, CDTWebSocketAdapter.class); + }); + WebSocketUpgradeFilter.configure(jsonServletContextHandler); + try (V8Runtime v8Runtime = V8Host.getV8Instance().createV8Runtime()) { + jsonServer.start(); + logger.logInfo("Server is started. Please press any key to stop the server."); + System.out.println("Welcome to CDT Shell!"); + System.out.println("Input the script or '" + CDTConfig.COMMAND_EXIT + "' to exit."); + CDTConfig.setV8Runtime(v8Runtime); + try (Scanner scanner = new Scanner(System.in)) { + while (true) { + System.out.print("> "); + String command = scanner.nextLine(); + if (CDTConfig.COMMAND_EXIT.equals(command)) { + break; + } + try (V8Value v8Value = v8Runtime.getExecutor(command).execute()) { + if (v8Value != null) { + System.out.println(v8Value.toString()); + } + } catch (Throwable t) { + System.err.println(t.getMessage()); + } + } + } + } finally { + CDTConfig.setV8Runtime(null); + } + } catch (Throwable t) { + logger.logError(t, t.getMessage()); + } finally { + if (jsonServer.isStarted() || jsonServer.isStarting()) { + logger.logInfo("Server is being stopped."); + try { + jsonServer.stop(); + } catch (Throwable t) { + logger.logError(t, t.getMessage()); + } + logger.logInfo("Server is stopped."); + } + } + + } + +} diff --git a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTWebSocketAdapter.java b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTWebSocketAdapter.java index 14348d310..0565e8e9f 100644 --- a/src/test/java/com/caoccao/javet/tutorial/cdt/CDTWebSocketAdapter.java +++ b/src/test/java/com/caoccao/javet/tutorial/cdt/CDTWebSocketAdapter.java @@ -1,102 +1,102 @@ -/* - * 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.tutorial.cdt; - -import com.caoccao.javet.interfaces.IJavetLogger; -import com.caoccao.javet.interop.IV8InspectorListener; -import com.caoccao.javet.utils.JavetDefaultLogger; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; - -public class CDTWebSocketAdapter extends WebSocketAdapter implements IV8InspectorListener { - protected IJavetLogger logger; - protected Session session; - - public CDTWebSocketAdapter() { - this.logger = new JavetDefaultLogger(getClass().getName()); - logger.logInfo("CDTWebSocketAdapter()"); - session = null; - } - - @Override - public void flushProtocolNotifications() { - } - - @Override - public void onWebSocketClose(int statusCode, String reason) { - logger.logInfo("onWebSocketClose(): {0} {1}", Integer.toString(statusCode), reason); - session = null; - CDTConfig.getV8Runtime().getV8Inspector().removeListeners(this); - } - - @Override - public void onWebSocketConnect(Session session) { - logger.logInfo("onWebSocketConnect(): {0}", session.getRemoteAddress().toString()); - this.session = session; - CDTConfig.getV8Runtime().getV8Inspector().addListeners(this); - } - - @Override - public void onWebSocketError(Throwable cause) { - logger.logError(cause, cause.getMessage()); - } - - @Override - public void onWebSocketText(String message) { - logger.logInfo("onWebSocketText(): {0}", message); - try { - CDTConfig.getV8Runtime().getV8Inspector().sendRequest(message); - } catch (Exception e) { - logger.logError(e, e.getMessage()); - } - } - - @Override - public void receiveNotification(String message) { - logger.logInfo("receiveNotification(): {0}", message); - try { - session.getRemote().sendString(message); - } catch (Exception e) { - logger.logError(e, e.getMessage()); - } - } - - @Override - public void receiveResponse(String message) { - logger.logInfo("receiveResponse(): {0}", message); - try { - session.getRemote().sendString(message); - } catch (Exception e) { - logger.logError(e, e.getMessage()); - } - } - - @Override - public void runIfWaitingForDebugger(int contextGroupId) { - try { - CDTConfig.getV8Runtime().getExecutor( - "console.log('Welcome to Javet Debugging Environment!');").executeVoid(); - } catch (Exception e) { - logger.logError(e, e.getMessage()); - } - } - - @Override - public void sendRequest(String message) { - } -} +/* + * 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.tutorial.cdt; + +import com.caoccao.javet.interfaces.IJavetLogger; +import com.caoccao.javet.interop.IV8InspectorListener; +import com.caoccao.javet.utils.JavetDefaultLogger; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.WebSocketAdapter; + +public class CDTWebSocketAdapter extends WebSocketAdapter implements IV8InspectorListener { + protected IJavetLogger logger; + protected Session session; + + public CDTWebSocketAdapter() { + this.logger = new JavetDefaultLogger(getClass().getName()); + logger.logInfo("CDTWebSocketAdapter()"); + session = null; + } + + @Override + public void flushProtocolNotifications() { + } + + @Override + public void onWebSocketClose(int statusCode, String reason) { + logger.logInfo("onWebSocketClose(): {0} {1}", Integer.toString(statusCode), reason); + session = null; + CDTConfig.getV8Runtime().getV8Inspector().removeListeners(this); + } + + @Override + public void onWebSocketConnect(Session session) { + logger.logInfo("onWebSocketConnect(): {0}", session.getRemoteAddress().toString()); + this.session = session; + CDTConfig.getV8Runtime().getV8Inspector().addListeners(this); + } + + @Override + public void onWebSocketError(Throwable cause) { + logger.logError(cause, cause.getMessage()); + } + + @Override + public void onWebSocketText(String message) { + logger.logInfo("onWebSocketText(): {0}", message); + try { + CDTConfig.getV8Runtime().getV8Inspector().sendRequest(message); + } catch (Exception e) { + logger.logError(e, e.getMessage()); + } + } + + @Override + public void receiveNotification(String message) { + logger.logInfo("receiveNotification(): {0}", message); + try { + session.getRemote().sendString(message); + } catch (Exception e) { + logger.logError(e, e.getMessage()); + } + } + + @Override + public void receiveResponse(String message) { + logger.logInfo("receiveResponse(): {0}", message); + try { + session.getRemote().sendString(message); + } catch (Exception e) { + logger.logError(e, e.getMessage()); + } + } + + @Override + public void runIfWaitingForDebugger(int contextGroupId) { + try { + CDTConfig.getV8Runtime().getExecutor( + "console.log('Welcome to Javet Debugging Environment!');").executeVoid(); + } catch (Exception e) { + logger.logError(e, e.getMessage()); + } + } + + @Override + public void sendRequest(String message) { + } +} diff --git a/src/test/java/com/caoccao/javet/tutorial/cdt/TestCDT.java b/src/test/java/com/caoccao/javet/tutorial/cdt/TestCDT.java index dc495e8a7..5b8161017 100644 --- a/src/test/java/com/caoccao/javet/tutorial/cdt/TestCDT.java +++ b/src/test/java/com/caoccao/javet/tutorial/cdt/TestCDT.java @@ -1,35 +1,35 @@ -/* - * 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.tutorial.cdt; - -/* -This is a sample application that demonstrates how Javet works with Chrome Developer Tools (aka. CDT). - -Usage: -1. Run this application and the following 2 service endpoints will be open. - http://localhost:9229/json - ws://localhost:9229/javet -2. Open URL "chrome://inspect/" in Chrome. -3. Wait a few seconds and click "Javet" to open CDT. - */ -public class TestCDT { - public static void main(String[] args) { - CDTShell cdtShell = new CDTShell(); - cdtShell.run(); - } -} +/* + * 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.tutorial.cdt; + +/* +This is a sample application that demonstrates how Javet works with Chrome Developer Tools (aka. CDT). + +Usage: +1. Run this application and the following 2 service endpoints will be open. + http://localhost:9229/json + ws://localhost:9229/javet +2. Open URL "chrome://inspect/" in Chrome. +3. Wait a few seconds and click "Javet" to open CDT. + */ +public class TestCDT { + public static void main(String[] args) { + CDTShell cdtShell = new CDTShell(); + cdtShell.run(); + } +} diff --git a/src/test/java/com/caoccao/javet/utils/TestSimpleFreeMarkerFormat.java b/src/test/java/com/caoccao/javet/utils/TestSimpleFreeMarkerFormat.java index cfb717cd8..92a1f2cdf 100644 --- a/src/test/java/com/caoccao/javet/utils/TestSimpleFreeMarkerFormat.java +++ b/src/test/java/com/caoccao/javet/utils/TestSimpleFreeMarkerFormat.java @@ -1,73 +1,73 @@ -/* - * 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.utils; - -import org.junit.jupiter.api.Test; - -import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class TestSimpleFreeMarkerFormat { - @Test - public void testInvalid() { - assertEquals("abc", - SimpleFreeMarkerFormat.format("abc", null), - "Parameters being null should pass."); - assertEquals("abc", - SimpleFreeMarkerFormat.format("abc", new HashMap<>()), - "Parameters being empty should pass."); - assertEquals("abc${", - SimpleFreeMarkerFormat.format("abc${", SimpleMap.of("d", "x")), - "Open variable should pass."); - assertEquals("abc${def", - SimpleFreeMarkerFormat.format("abc${def", SimpleMap.of("d", "x")), - "Open variable should pass."); - assertEquals("abc$${d}", - SimpleFreeMarkerFormat.format("abc$${d}", SimpleMap.of("d", "x")), - "Double dollar should pass."); - assertEquals("abcdef", - SimpleFreeMarkerFormat.format("abc${e}def", SimpleMap.of("d", "x")), - "Unknown variable should pass."); - assertEquals("abcdef", - SimpleFreeMarkerFormat.format("abc${}def", SimpleMap.of("d", "x")), - "Empty variable should pass."); - assertEquals("ab{def.$ghi}c", - SimpleFreeMarkerFormat.format("ab{def.$ghi}c", SimpleMap.of("ghi", "x")), - "Dollar should pass."); - } - - @Test - public void testValid() { - assertEquals("abcx", - SimpleFreeMarkerFormat.format("abc${d}", SimpleMap.of("d", "x")), - "Variable at the end should pass."); - assertEquals("xabc", - SimpleFreeMarkerFormat.format("${d}abc", SimpleMap.of("d", "x")), - "Variable at the beginning should pass."); - assertEquals("abxc", - SimpleFreeMarkerFormat.format("ab${d}c", SimpleMap.of("d", "x")), - "Variable in the middle should pass."); - assertEquals("abxc", - SimpleFreeMarkerFormat.format("ab${def.${ghi}c", SimpleMap.of("def.${ghi", "x")), - "Variable with dollar should pass."); - assertEquals("abxc", - SimpleFreeMarkerFormat.format("ab${{}c", SimpleMap.of("{", "x")), - "Single open should pass."); - } -} +/* + * 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.utils; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestSimpleFreeMarkerFormat { + @Test + public void testInvalid() { + assertEquals("abc", + SimpleFreeMarkerFormat.format("abc", null), + "Parameters being null should pass."); + assertEquals("abc", + SimpleFreeMarkerFormat.format("abc", new HashMap<>()), + "Parameters being empty should pass."); + assertEquals("abc${", + SimpleFreeMarkerFormat.format("abc${", SimpleMap.of("d", "x")), + "Open variable should pass."); + assertEquals("abc${def", + SimpleFreeMarkerFormat.format("abc${def", SimpleMap.of("d", "x")), + "Open variable should pass."); + assertEquals("abc$${d}", + SimpleFreeMarkerFormat.format("abc$${d}", SimpleMap.of("d", "x")), + "Double dollar should pass."); + assertEquals("abcdef", + SimpleFreeMarkerFormat.format("abc${e}def", SimpleMap.of("d", "x")), + "Unknown variable should pass."); + assertEquals("abcdef", + SimpleFreeMarkerFormat.format("abc${}def", SimpleMap.of("d", "x")), + "Empty variable should pass."); + assertEquals("ab{def.$ghi}c", + SimpleFreeMarkerFormat.format("ab{def.$ghi}c", SimpleMap.of("ghi", "x")), + "Dollar should pass."); + } + + @Test + public void testValid() { + assertEquals("abcx", + SimpleFreeMarkerFormat.format("abc${d}", SimpleMap.of("d", "x")), + "Variable at the end should pass."); + assertEquals("xabc", + SimpleFreeMarkerFormat.format("${d}abc", SimpleMap.of("d", "x")), + "Variable at the beginning should pass."); + assertEquals("abxc", + SimpleFreeMarkerFormat.format("ab${d}c", SimpleMap.of("d", "x")), + "Variable in the middle should pass."); + assertEquals("abxc", + SimpleFreeMarkerFormat.format("ab${def.${ghi}c", SimpleMap.of("def.${ghi", "x")), + "Variable with dollar should pass."); + assertEquals("abxc", + SimpleFreeMarkerFormat.format("ab${{}c", SimpleMap.of("{", "x")), + "Single open should pass."); + } +} diff --git a/src/test/java/com/caoccao/javet/values/reference/TestV8Module.java b/src/test/java/com/caoccao/javet/values/reference/TestV8Module.java index aa2826222..03d698cc2 100644 --- a/src/test/java/com/caoccao/javet/values/reference/TestV8Module.java +++ b/src/test/java/com/caoccao/javet/values/reference/TestV8Module.java @@ -1,224 +1,224 @@ -/* - * 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.values.reference; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetCompilationException; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interop.executors.IV8Executor; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class TestV8Module extends BaseTestJavetRuntime { - @Test - public void testExecute() throws JavetException { - IV8Executor iV8Executor = v8Runtime.getExecutor( - "Object.a = 1").setResourceName("./test.js"); - try (V8Module v8Module = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module.getResourceName())); - assertEquals(1, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(4, v8Module.getScriptId()); - } - assertEquals("./test.js", v8Module.getResourceName()); - try (V8ValuePromise v8ValuePromise = v8Module.execute()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - assertEquals(V8Module.Evaluated, v8Module.getStatus()); - assertNull(v8Module.getException()); - assertEquals(1, v8Runtime.getExecutor("Object.a").executeInteger()); - try (V8ValueObject v8ValueObject = v8Module.getNamespace()) { - assertNotNull(v8ValueObject); - } - } - } - - @Test - public void testImportInvalidModuleInModule() throws JavetException { - String codeString1 = "export function test1() {\n" + - " return { x: 1, y: 2, z: 3 };\n" + - "}"; - String codeString2 = "import { test9 } from './module1.js';\n" + - "export const test2 = test9;"; - String codeString3 = "import { test1 } from './module9.js';\n" + - "export const test2 = test1;"; - String moduleName1 = "./module1.js"; - String moduleName2 = "./module2.js"; - String moduleName3 = "./module3.js"; - IV8Executor iV8Executor = v8Runtime.getExecutor(codeString1).setResourceName(moduleName1); - try (V8Module v8Module1 = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module1.getResourceName())); - assertEquals(1, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(4, v8Module1.getScriptId()); - } - assertTrue(v8Module1.instantiate()); - try (V8ValuePromise v8ValuePromise = v8Module1.evaluate()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - iV8Executor = v8Runtime.getExecutor(codeString2).setResourceName(moduleName2); - try (V8Module v8Module2 = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module2.getResourceName())); - assertEquals(2, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(5, v8Module2.getScriptId()); - } - assertFalse(v8Module2.instantiate(), "Function is invalid"); - assertNull(v8Module2.getException()); - } - iV8Executor = v8Runtime.getExecutor(codeString3).setResourceName(moduleName3); - try (V8Module v8Module3 = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module3.getResourceName())); - assertEquals(2, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(6, v8Module3.getScriptId()); - } - assertFalse(v8Module3.instantiate(), "Module is invalid"); - assertNull(v8Module3.getException()); - } - } - } - - @Test - public void testImportValidModuleAndExecute() throws JavetException { - String codeString = "export function test() { return { a: 1 }; };"; - IV8Executor iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./test.js"); - try (V8Module v8Module = iV8Executor.compileV8Module()) { - if (v8Runtime.getJSRuntimeType().isNode()) { - v8Runtime.getExecutor("const process = require('process');\n" + - "var globalReason = null;\n" + - "process.on('unhandledRejection', (reason, promise) => {\n" + - " globalReason = reason;\n" + - "});").executeVoid(); - } - try (V8ValuePromise v8ValuePromise = v8Module.execute()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - // Import in module is supported. - codeString = "import { test } from './test.js'; test();"; - iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./a.js").setModule(true); - try (V8ValueObject v8ValueObject = iV8Executor.execute()) { - assertNotNull(v8ValueObject); - V8ValuePromise v8ValuePromise = (V8ValuePromise) v8ValueObject; - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertFalse(v8Runtime.containsV8Module("./a.js")); - } - } - // V8: Dynamic import is not supported. - // Node: UnhandledPromiseRejectionWarning: TypeError: Invalid host defined options. - codeString = "const p = import('./test.js'); p;"; - iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./a.js").setModule(false); - try (V8ValuePromise v8ValuePromise = iV8Executor.execute()) { - assertNotNull(v8ValuePromise); - assertTrue(v8ValuePromise.isRejected()); - } - } - } - - @Test - public void testImportValidModuleInModule() throws JavetException { - String codeString1 = "export function test1() {\n" + - " return { x: 1, y: 2, z: 3 };\n" + - "}"; - String codeString2 = "import { test1 } from './module1.js';\n" + - "export const test2 = test1;"; - String moduleName1 = "./module1.js"; - String moduleName2 = "./module2.js"; - IV8Executor iV8Executor = v8Runtime.getExecutor(codeString1).setResourceName(moduleName1); - try (V8Module v8Module1 = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module1.getResourceName())); - assertEquals(1, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(4, v8Module1.getScriptId()); - } - assertTrue(v8Module1.instantiate()); - try (V8ValuePromise v8ValuePromise = v8Module1.evaluate()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - try (V8ValueObject v8ValueObject = v8Module1.getNamespace()) { - assertNotNull(v8ValueObject); - try (V8ValueFunction v8ValueFunction = v8ValueObject.get("test1")) { - assertEquals(codeString1.substring(7), v8ValueFunction.toString()); - } - } - iV8Executor = v8Runtime.getExecutor(codeString2).setResourceName(moduleName2); - try (V8Module v8Module2 = iV8Executor.compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module2.getResourceName())); - assertEquals(2, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(5, v8Module2.getScriptId()); - } - assertTrue(v8Module2.instantiate()); - try (V8ValuePromise v8ValuePromise = v8Module2.evaluate()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - try (V8ValueObject v8ValueObject = v8Module2.getNamespace()) { - assertNotNull(v8ValueObject); - try (V8ValueFunction v8ValueFunction = v8ValueObject.get("test2")) { - assertEquals(codeString1.substring(7), v8ValueFunction.toString()); - } - } - } - } - } - - @Test - public void testStatusConversion() throws JavetException { - try (V8Module v8Module = v8Runtime.getExecutor( - "export function test() { return 1; }").setResourceName("./test.js").compileV8Module()) { - assertTrue(v8Runtime.containsV8Module(v8Module.getResourceName())); - assertEquals(1, v8Runtime.getV8ModuleCount()); - if (v8Runtime.getJSRuntimeType().isV8()) { - assertEquals(4, v8Module.getScriptId()); - } - assertNotNull(v8Module); - assertEquals(V8Module.Uninstantiated, v8Module.getStatus()); - assertNull(v8Module.getException()); - assertTrue(v8Module.instantiate()); - assertEquals(V8Module.Instantiated, v8Module.getStatus()); - assertFalse(v8Module.instantiate()); - assertNull(v8Module.getException()); - try (V8ValuePromise v8ValuePromise = v8Module.evaluate()) { - assertTrue(v8ValuePromise.isFulfilled()); - assertTrue(v8ValuePromise.getResult().isUndefined()); - } - assertEquals(V8Module.Evaluated, v8Module.getStatus()); - assertNull(v8Module.getException()); - } - } - - @Test - public void testUnexpectedIdentifier() throws JavetException { - try (V8Module v8Module = v8Runtime.getExecutor( - "a b c").setResourceName("./test.js").compileV8Module()) { - fail("Failed to report error."); - } catch (JavetCompilationException e) { - assertFalse(v8Runtime.containsV8Module("./test.js")); - assertEquals(0, v8Runtime.getV8ModuleCount()); - assertEquals("SyntaxError: Unexpected identifier", e.getScriptingError().getMessage()); - } - } -} +/* + * 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.values.reference; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetCompilationException; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interop.executors.IV8Executor; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestV8Module extends BaseTestJavetRuntime { + @Test + public void testExecute() throws JavetException { + IV8Executor iV8Executor = v8Runtime.getExecutor( + "Object.a = 1").setResourceName("./test.js"); + try (V8Module v8Module = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module.getResourceName())); + assertEquals(1, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(4, v8Module.getScriptId()); + } + assertEquals("./test.js", v8Module.getResourceName()); + try (V8ValuePromise v8ValuePromise = v8Module.execute()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + assertEquals(V8Module.Evaluated, v8Module.getStatus()); + assertNull(v8Module.getException()); + assertEquals(1, v8Runtime.getExecutor("Object.a").executeInteger()); + try (V8ValueObject v8ValueObject = v8Module.getNamespace()) { + assertNotNull(v8ValueObject); + } + } + } + + @Test + public void testImportInvalidModuleInModule() throws JavetException { + String codeString1 = "export function test1() {\n" + + " return { x: 1, y: 2, z: 3 };\n" + + "}"; + String codeString2 = "import { test9 } from './module1.js';\n" + + "export const test2 = test9;"; + String codeString3 = "import { test1 } from './module9.js';\n" + + "export const test2 = test1;"; + String moduleName1 = "./module1.js"; + String moduleName2 = "./module2.js"; + String moduleName3 = "./module3.js"; + IV8Executor iV8Executor = v8Runtime.getExecutor(codeString1).setResourceName(moduleName1); + try (V8Module v8Module1 = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module1.getResourceName())); + assertEquals(1, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(4, v8Module1.getScriptId()); + } + assertTrue(v8Module1.instantiate()); + try (V8ValuePromise v8ValuePromise = v8Module1.evaluate()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + iV8Executor = v8Runtime.getExecutor(codeString2).setResourceName(moduleName2); + try (V8Module v8Module2 = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module2.getResourceName())); + assertEquals(2, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(5, v8Module2.getScriptId()); + } + assertFalse(v8Module2.instantiate(), "Function is invalid"); + assertNull(v8Module2.getException()); + } + iV8Executor = v8Runtime.getExecutor(codeString3).setResourceName(moduleName3); + try (V8Module v8Module3 = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module3.getResourceName())); + assertEquals(2, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(6, v8Module3.getScriptId()); + } + assertFalse(v8Module3.instantiate(), "Module is invalid"); + assertNull(v8Module3.getException()); + } + } + } + + @Test + public void testImportValidModuleAndExecute() throws JavetException { + String codeString = "export function test() { return { a: 1 }; };"; + IV8Executor iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./test.js"); + try (V8Module v8Module = iV8Executor.compileV8Module()) { + if (v8Runtime.getJSRuntimeType().isNode()) { + v8Runtime.getExecutor("const process = require('process');\n" + + "var globalReason = null;\n" + + "process.on('unhandledRejection', (reason, promise) => {\n" + + " globalReason = reason;\n" + + "});").executeVoid(); + } + try (V8ValuePromise v8ValuePromise = v8Module.execute()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + // Import in module is supported. + codeString = "import { test } from './test.js'; test();"; + iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./a.js").setModule(true); + try (V8ValueObject v8ValueObject = iV8Executor.execute()) { + assertNotNull(v8ValueObject); + V8ValuePromise v8ValuePromise = (V8ValuePromise) v8ValueObject; + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertFalse(v8Runtime.containsV8Module("./a.js")); + } + } + // V8: Dynamic import is not supported. + // Node: UnhandledPromiseRejectionWarning: TypeError: Invalid host defined options. + codeString = "const p = import('./test.js'); p;"; + iV8Executor = v8Runtime.getExecutor(codeString).setResourceName("./a.js").setModule(false); + try (V8ValuePromise v8ValuePromise = iV8Executor.execute()) { + assertNotNull(v8ValuePromise); + assertTrue(v8ValuePromise.isRejected()); + } + } + } + + @Test + public void testImportValidModuleInModule() throws JavetException { + String codeString1 = "export function test1() {\n" + + " return { x: 1, y: 2, z: 3 };\n" + + "}"; + String codeString2 = "import { test1 } from './module1.js';\n" + + "export const test2 = test1;"; + String moduleName1 = "./module1.js"; + String moduleName2 = "./module2.js"; + IV8Executor iV8Executor = v8Runtime.getExecutor(codeString1).setResourceName(moduleName1); + try (V8Module v8Module1 = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module1.getResourceName())); + assertEquals(1, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(4, v8Module1.getScriptId()); + } + assertTrue(v8Module1.instantiate()); + try (V8ValuePromise v8ValuePromise = v8Module1.evaluate()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + try (V8ValueObject v8ValueObject = v8Module1.getNamespace()) { + assertNotNull(v8ValueObject); + try (V8ValueFunction v8ValueFunction = v8ValueObject.get("test1")) { + assertEquals(codeString1.substring(7), v8ValueFunction.toString()); + } + } + iV8Executor = v8Runtime.getExecutor(codeString2).setResourceName(moduleName2); + try (V8Module v8Module2 = iV8Executor.compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module2.getResourceName())); + assertEquals(2, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(5, v8Module2.getScriptId()); + } + assertTrue(v8Module2.instantiate()); + try (V8ValuePromise v8ValuePromise = v8Module2.evaluate()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + try (V8ValueObject v8ValueObject = v8Module2.getNamespace()) { + assertNotNull(v8ValueObject); + try (V8ValueFunction v8ValueFunction = v8ValueObject.get("test2")) { + assertEquals(codeString1.substring(7), v8ValueFunction.toString()); + } + } + } + } + } + + @Test + public void testStatusConversion() throws JavetException { + try (V8Module v8Module = v8Runtime.getExecutor( + "export function test() { return 1; }").setResourceName("./test.js").compileV8Module()) { + assertTrue(v8Runtime.containsV8Module(v8Module.getResourceName())); + assertEquals(1, v8Runtime.getV8ModuleCount()); + if (v8Runtime.getJSRuntimeType().isV8()) { + assertEquals(4, v8Module.getScriptId()); + } + assertNotNull(v8Module); + assertEquals(V8Module.Uninstantiated, v8Module.getStatus()); + assertNull(v8Module.getException()); + assertTrue(v8Module.instantiate()); + assertEquals(V8Module.Instantiated, v8Module.getStatus()); + assertFalse(v8Module.instantiate()); + assertNull(v8Module.getException()); + try (V8ValuePromise v8ValuePromise = v8Module.evaluate()) { + assertTrue(v8ValuePromise.isFulfilled()); + assertTrue(v8ValuePromise.getResult().isUndefined()); + } + assertEquals(V8Module.Evaluated, v8Module.getStatus()); + assertNull(v8Module.getException()); + } + } + + @Test + public void testUnexpectedIdentifier() throws JavetException { + try (V8Module v8Module = v8Runtime.getExecutor( + "a b c").setResourceName("./test.js").compileV8Module()) { + fail("Failed to report error."); + } catch (JavetCompilationException e) { + assertFalse(v8Runtime.containsV8Module("./test.js")); + assertEquals(0, v8Runtime.getV8ModuleCount()); + assertEquals("SyntaxError: Unexpected identifier", e.getScriptingError().getMessage()); + } + } +} diff --git a/src/test/java/com/caoccao/javet/values/reference/TestV8Script.java b/src/test/java/com/caoccao/javet/values/reference/TestV8Script.java index af83b3cdf..225f7c159 100644 --- a/src/test/java/com/caoccao/javet/values/reference/TestV8Script.java +++ b/src/test/java/com/caoccao/javet/values/reference/TestV8Script.java @@ -1,47 +1,47 @@ -/* - * 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.values.reference; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetCompilationException; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interop.executors.IV8Executor; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class TestV8Script extends BaseTestJavetRuntime { - @Test - public void testExecute() throws JavetException { - IV8Executor iV8Executor = v8Runtime.getExecutor( - "const a = 1; a;").setResourceName("./test.js"); - try (V8Script v8Script = iV8Executor.compileScript()) { - assertNotNull(v8Script); - assertEquals(1, v8Script.executeInteger()); - } - } - - @Test - public void testUnexpectedIdentifier() throws JavetException { - try (V8Script v8Script = v8Runtime.getExecutor("a b c").compileScript()) { - fail("Failed to report error."); - } catch (JavetCompilationException e) { - assertEquals("SyntaxError: Unexpected identifier", e.getScriptingError().getMessage()); - } - } -} +/* + * 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.values.reference; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetCompilationException; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interop.executors.IV8Executor; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestV8Script extends BaseTestJavetRuntime { + @Test + public void testExecute() throws JavetException { + IV8Executor iV8Executor = v8Runtime.getExecutor( + "const a = 1; a;").setResourceName("./test.js"); + try (V8Script v8Script = iV8Executor.compileScript()) { + assertNotNull(v8Script); + assertEquals(1, v8Script.executeInteger()); + } + } + + @Test + public void testUnexpectedIdentifier() throws JavetException { + try (V8Script v8Script = v8Runtime.getExecutor("a b c").compileScript()) { + fail("Failed to report error."); + } catch (JavetCompilationException e) { + assertEquals("SyntaxError: Unexpected identifier", e.getScriptingError().getMessage()); + } + } +} diff --git a/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInJson.java b/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInJson.java index 7aad41fbb..acff225e4 100644 --- a/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInJson.java +++ b/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInJson.java @@ -1,36 +1,53 @@ -package com.caoccao.javet.values.reference.builtin; - -import com.caoccao.javet.BaseTestJavetRuntime; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.exceptions.JavetExecutionException; -import com.caoccao.javet.values.reference.V8ValueObject; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class TestV8ValueBuiltInJson extends BaseTestJavetRuntime { - @Test - public void testCircularStructure() throws JavetException { - String codeString = "const a = {x: 1};\n" + - "var b = {y: a, z: 2};\n" + - "a.x = b;"; - v8Runtime.getExecutor(codeString).executeVoid(); - try (V8ValueObject v8ValueObject = v8Runtime.getGlobalObject().get("b")) { - assertEquals(2, v8ValueObject.getInteger("z")); - try (V8ValueBuiltInJson v8ValueBuiltInJson = v8Runtime.getGlobalObject().getJson()) { - v8ValueBuiltInJson.stringify(v8ValueObject); - } catch (JavetExecutionException e) { - assertEquals( - "TypeError: Converting circular structure to JSON\n" + - " --> starting at object with constructor 'Object'\n" + - " | property 'y' -> object with constructor 'Object'\n" + - " --- property 'x' closes the circle", - e.getMessage()); - } - assertThrows(StackOverflowError.class, () -> { - Object b = v8Runtime.toObject(v8ValueObject); - }); - } - } -} +/* + * 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.values.reference.builtin; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.exceptions.JavetExecutionException; +import com.caoccao.javet.values.reference.V8ValueObject; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class TestV8ValueBuiltInJson extends BaseTestJavetRuntime { + @Test + public void testCircularStructure() throws JavetException { + String codeString = "const a = {x: 1};\n" + + "var b = {y: a, z: 2};\n" + + "a.x = b;"; + v8Runtime.getExecutor(codeString).executeVoid(); + try (V8ValueObject v8ValueObject = v8Runtime.getGlobalObject().get("b")) { + assertEquals(2, v8ValueObject.getInteger("z")); + try (V8ValueBuiltInJson v8ValueBuiltInJson = v8Runtime.getGlobalObject().getBuiltInJson()) { + v8ValueBuiltInJson.stringify(v8ValueObject); + } catch (JavetExecutionException e) { + assertEquals( + "TypeError: Converting circular structure to JSON\n" + + " --> starting at object with constructor 'Object'\n" + + " | property 'y' -> object with constructor 'Object'\n" + + " --- property 'x' closes the circle", + e.getMessage()); + } + assertThrows(StackOverflowError.class, () -> { + Object b = v8Runtime.toObject(v8ValueObject); + }); + } + } +} diff --git a/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInObject.java b/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInObject.java new file mode 100644 index 000000000..d5ebdb19a --- /dev/null +++ b/src/test/java/com/caoccao/javet/values/reference/builtin/TestV8ValueBuiltInObject.java @@ -0,0 +1,44 @@ +/* + * 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.values.reference.builtin; + +import com.caoccao.javet.BaseTestJavetRuntime; +import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.values.reference.V8ValueObject; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestV8ValueBuiltInObject extends BaseTestJavetRuntime { + @Test + public void testAssign() throws JavetException { + String codeString = "var a = {x: 1};\n" + + "var b = {y: 2};\n"; + v8Runtime.getExecutor(codeString).executeVoid(); + try (V8ValueObject v8ValueObjectA = v8Runtime.getGlobalObject().get("a"); + V8ValueObject v8ValueObjectB = v8Runtime.getGlobalObject().get("b")) { + assertEquals(1, v8ValueObjectA.getInteger("x")); + assertEquals(2, v8ValueObjectB.getInteger("y")); + try (V8ValueBuiltInObject V8ValueBuiltInObject = v8Runtime.getGlobalObject().getBuiltInObject()) { + try (V8ValueObject v8ValueObjectC = V8ValueBuiltInObject.assign(v8ValueObjectA, v8ValueObjectB)) { + assertEquals("{\"x\":1,\"y\":2}", v8ValueObjectC.toJsonString()); + } + } + } + } +}