From 3844628a6a822897131416c4a765bfbef2ddf961 Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Fri, 7 Jun 2024 17:05:21 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20#351=20Add=20isSealed=20to?= =?UTF-8?q?=20V8ValueObject?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cpp/jni/com_caoccao_javet_interop_V8Native.h | 8 + cpp/jni/javet_converter.cpp | 33 +--- cpp/jni/javet_jni_object.cpp | 15 ++ docs/release_notes/release_notes_3_1.rst | 3 +- .../com/caoccao/javet/interop/IV8Native.java | 2 + .../com/caoccao/javet/interop/V8Internal.java | 12 +- .../com/caoccao/javet/interop/V8Native.java | 3 + .../com/caoccao/javet/interop/V8Runtime.java | 35 +++- .../converters/JavetObjectConverter.java | 7 +- .../javet/values/reference/IV8ValueArray.java | 148 +++++++++++++- .../values/reference/IV8ValueObject.java | 9 + .../values/reference/IV8ValueSealedArray.java | 182 ------------------ .../javet/values/reference/V8ValueArray.java | 130 ++++++++++++- .../javet/values/reference/V8ValueObject.java | 5 + .../values/reference/V8ValueSealedArray.java | 165 ---------------- .../converters/TestJavetObjectConverter.java | 27 +-- .../values/reference/TestV8ValueObject.java | 10 + .../reference/TestV8ValueSealedArray.java | 38 ---- 18 files changed, 383 insertions(+), 449 deletions(-) delete mode 100644 src/main/java/com/caoccao/javet/values/reference/IV8ValueSealedArray.java delete mode 100644 src/main/java/com/caoccao/javet/values/reference/V8ValueSealedArray.java delete mode 100644 src/test/java/com/caoccao/javet/values/reference/TestV8ValueSealedArray.java diff --git a/cpp/jni/com_caoccao_javet_interop_V8Native.h b/cpp/jni/com_caoccao_javet_interop_V8Native.h index 540882716..8957a01e1 100644 --- a/cpp/jni/com_caoccao_javet_interop_V8Native.h +++ b/cpp/jni/com_caoccao_javet_interop_V8Native.h @@ -951,6 +951,14 @@ JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_objectHasPriv JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_objectInvoke (JNIEnv *, jobject, jlong, jlong, jint, jstring, jboolean, jobjectArray); +/* + * Class: com_caoccao_javet_interop_V8Native + * Method: objectIsSealed + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_objectIsSealed + (JNIEnv *, jobject, jlong, jlong); + /* * Class: com_caoccao_javet_interop_V8Native * Method: objectSet diff --git a/cpp/jni/javet_converter.cpp b/cpp/jni/javet_converter.cpp index b6fc8d2e7..677fbdec3 100644 --- a/cpp/jni/javet_converter.cpp +++ b/cpp/jni/javet_converter.cpp @@ -159,10 +159,6 @@ namespace Javet { jmethodID jmethodIDV8ValueRegExpConstructor; jmethodID jmethodIDV8ValueRegExpGetHandle; - jclass jclassV8ValueSealedArray; - jmethodID jmethodIDV8ValueSealedArrayConstructor; - jmethodID jmethodIDV8ValueSealedArrayGetHandle; - jclass jclassV8ValueSet; jmethodID jmethodIDV8ValueSetConstructor; jmethodID jmethodIDV8ValueSetGetHandle; @@ -482,10 +478,6 @@ namespace Javet { jmethodIDV8ValueRegExpConstructor = GET_METHOD_CONSTRUCTOR(jniEnv, jclassV8ValueRegExp); jmethodIDV8ValueRegExpGetHandle = GET_METHOD_GET_HANDLE(jniEnv, jclassV8ValueRegExp); - jclassV8ValueSealedArray = FIND_CLASS(jniEnv, "com/caoccao/javet/values/reference/V8ValueSealedArray"); - jmethodIDV8ValueSealedArrayConstructor = GET_METHOD_CONSTRUCTOR(jniEnv, jclassV8ValueSealedArray); - jmethodIDV8ValueSealedArrayGetHandle = GET_METHOD_GET_HANDLE(jniEnv, jclassV8ValueSealedArray); - jclassV8ValueSet = FIND_CLASS(jniEnv, "com/caoccao/javet/values/reference/V8ValueSet"); jmethodIDV8ValueSetConstructor = GET_METHOD_CONSTRUCTOR(jniEnv, jclassV8ValueSet); jmethodIDV8ValueSetGetHandle = GET_METHOD_GET_HANDLE(jniEnv, jclassV8ValueSet); @@ -666,26 +658,11 @@ namespace Javet { // Reference types // Note: Reference types must be checked before primitive types are checked. if (v8Value->IsArray()) { - auto v8InternalJSObject = ToV8InternalJSObject(v8Value); -#ifdef ENABLE_NODE - auto elementKind = V8InternalJSObject::cast(v8InternalJSObject).GetElementsKind(); -#else - auto elementKind = V8InternalJSObject::cast(v8InternalJSObject)->GetElementsKind(); -#endif - if (v8::internal::IsSealedElementsKind(elementKind)) { - return jniEnv->NewObject( - jclassV8ValueSealedArray, - jmethodIDV8ValueSealedArrayConstructor, - v8Runtime->externalV8Runtime, - ToV8PersistentReference(v8Context, v8Value)); - } - else { - return jniEnv->NewObject( - jclassV8ValueArray, - jmethodIDV8ValueArrayConstructor, - v8Runtime->externalV8Runtime, - ToV8PersistentReference(v8Context, v8Value)); - } + return jniEnv->NewObject( + jclassV8ValueArray, + jmethodIDV8ValueArrayConstructor, + v8Runtime->externalV8Runtime, + ToV8PersistentReference(v8Context, v8Value)); } if (v8Value->IsTypedArray()) { int type = V8ValueReferenceType::Invalid; diff --git a/cpp/jni/javet_jni_object.cpp b/cpp/jni/javet_jni_object.cpp index c60001da0..ff1f5f48e 100644 --- a/cpp/jni/javet_jni_object.cpp +++ b/cpp/jni/javet_jni_object.cpp @@ -638,6 +638,21 @@ JNIEXPORT jobject JNICALL Java_com_caoccao_javet_interop_V8Native_objectInvoke return Javet::Converter::ToExternalV8ValueUndefined(jniEnv, v8Runtime); } +JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_objectIsSealed +(JNIEnv* jniEnv, jobject caller, jlong v8RuntimeHandle, jlong v8ValueHandle) { + RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle); + if (v8LocalValue->IsObject()) { + auto v8InternalJSObject = Javet::Converter::ToV8InternalJSObject(v8LocalValue); +#ifdef ENABLE_NODE + auto elementKind = V8InternalJSObject::cast(v8InternalJSObject).GetElementsKind(); +#else + auto elementKind = V8InternalJSObject::cast(v8InternalJSObject)->GetElementsKind(); +#endif + return v8::internal::IsSealedElementsKind(elementKind); + } + return false; +} + JNIEXPORT jboolean JNICALL Java_com_caoccao_javet_interop_V8Native_objectSet (JNIEnv* jniEnv, jobject caller, jlong v8RuntimeHandle, jlong v8ValueHandle, jint v8ValueType, jobjectArray keysAndValues) { RUNTIME_AND_VALUE_HANDLES_TO_OBJECTS_WITH_SCOPE(v8RuntimeHandle, v8ValueHandle); diff --git a/docs/release_notes/release_notes_3_1.rst b/docs/release_notes/release_notes_3_1.rst index d49853e57..6a3726b4c 100644 --- a/docs/release_notes/release_notes_3_1.rst +++ b/docs/release_notes/release_notes_3_1.rst @@ -13,7 +13,8 @@ Release Notes 3.1.x * Added ``JavetProxyPrototypeStore`` * Added ``getPrototypeOf()`` to ``IJavetDirectProxyHandler`` and ``JavetDirectProxyObjectHandler`` * Added ``getGuard()`` to ``V8Runtime`` -* Added ``V8ValueSealedArray`` +* Added ``isSealed`` to ``V8ValueObject`` +* Updated ``JavetObjectConverter`` to convert sealed array to ``Object[]`` instead of ``List`` * Replaced ``JavetEngineGuard`` with ``V8Guard`` * Removed ``executorService``, ``engineGuardCheckIntervalMillis`` from ``JavetEngineConfig`` * Patched V8 `Check failed: !IsFreeSpaceOrFillerMap(map) `_ diff --git a/src/main/java/com/caoccao/javet/interop/IV8Native.java b/src/main/java/com/caoccao/javet/interop/IV8Native.java index 334b0deaa..3bcb2a8b2 100644 --- a/src/main/java/com/caoccao/javet/interop/IV8Native.java +++ b/src/main/java/com/caoccao/javet/interop/IV8Native.java @@ -286,6 +286,8 @@ Object objectInvoke( long v8RuntimeHandle, long v8ValueHandle, int v8ValueType, String functionName, boolean returnResult, Object[] values); + boolean objectIsSealed(long v8RuntimeHandle, long v8ValueHandle); + boolean objectSet(long v8RuntimeHandle, long v8ValueHandle, int v8ValueType, Object[] keysAndValues); boolean objectSetAccessor( diff --git a/src/main/java/com/caoccao/javet/interop/V8Internal.java b/src/main/java/com/caoccao/javet/interop/V8Internal.java index 3a45e9a95..38337308a 100644 --- a/src/main/java/com/caoccao/javet/interop/V8Internal.java +++ b/src/main/java/com/caoccao/javet/interop/V8Internal.java @@ -39,8 +39,8 @@ public void addReference(IV8ValueReference iV8ValueReference) { v8Runtime.addReference(iV8ValueReference); } - public int arrayGetLength(IV8ValueSealedArray iV8ValueSealedArray) throws JavetException { - return v8Runtime.arrayGetLength(iV8ValueSealedArray); + public int arrayGetLength(IV8ValueArray iV8ValueArray) throws JavetException { + return v8Runtime.arrayGetLength(iV8ValueArray); } public int arrayGetLength(IV8ValueTypedArray iV8ValueTypedArray) throws JavetException { @@ -48,9 +48,9 @@ public int arrayGetLength(IV8ValueTypedArray iV8ValueTypedArray) throws JavetExc } public int batchArrayGet( - IV8ValueSealedArray iV8ValueSealedArray, V8Value[] v8Values, int startIndex, int endIndex) + IV8ValueArray iV8ValueArray, V8Value[] v8Values, int startIndex, int endIndex) throws JavetException { - return v8Runtime.batchArrayGet(iV8ValueSealedArray, v8Values, startIndex, endIndex); + return v8Runtime.batchArrayGet(iV8ValueArray, v8Values, startIndex, endIndex); } public int batchObjectGet( @@ -449,6 +449,10 @@ public T objectInvoke( return v8Runtime.objectInvoke(iV8ValueObject, functionName, returnResult, v8Values); } + public boolean objectIsSealed(IV8ValueObject iV8ValueObject) { + return v8Runtime.objectIsSealed(iV8ValueObject); + } + public boolean objectSet(IV8ValueObject iV8ValueObject, V8Value... v8Values) throws JavetException { return v8Runtime.objectSet(iV8ValueObject, v8Values); } diff --git a/src/main/java/com/caoccao/javet/interop/V8Native.java b/src/main/java/com/caoccao/javet/interop/V8Native.java index bb0d6488e..2a2c6249f 100644 --- a/src/main/java/com/caoccao/javet/interop/V8Native.java +++ b/src/main/java/com/caoccao/javet/interop/V8Native.java @@ -430,6 +430,9 @@ public native Object objectInvoke( long v8RuntimeHandle, long v8ValueHandle, int v8ValueType, String functionName, boolean returnResult, Object[] values); + @Override + public native boolean objectIsSealed(long v8RuntimeHandle, long v8ValueHandle) ; + @Override public native boolean objectSet( long v8RuntimeHandle, long v8ValueHandle, int v8ValueType, Object[] keysAndValues); diff --git a/src/main/java/com/caoccao/javet/interop/V8Runtime.java b/src/main/java/com/caoccao/javet/interop/V8Runtime.java index ebf9b25d7..774376a46 100644 --- a/src/main/java/com/caoccao/javet/interop/V8Runtime.java +++ b/src/main/java/com/caoccao/javet/interop/V8Runtime.java @@ -446,14 +446,14 @@ public void allowEval(boolean allow) { /** * Gets length from an array. * - * @param iV8ValueSealedArray the V8 value sealed array + * @param iV8ValueArray the V8 value array * @return the length * @throws JavetException the javet exception * @since 0.7.0 */ @SuppressWarnings("RedundantThrows") - int arrayGetLength(IV8ValueSealedArray iV8ValueSealedArray) throws JavetException { - return v8Native.arrayGetLength(handle, iV8ValueSealedArray.getHandle(), iV8ValueSealedArray.getType().getId()); + int arrayGetLength(IV8ValueArray iV8ValueArray) throws JavetException { + return v8Native.arrayGetLength(handle, iV8ValueArray.getHandle(), iV8ValueArray.getType().getId()); } /** @@ -496,20 +496,20 @@ public boolean await(V8AwaitMode v8AwaitMode) { /** * Get the given range of items from the array. * - * @param iV8ValueSealedArray the V8 value sealed array - * @param v8Values the V8 values - * @param startIndex the start index - * @param endIndex the end index + * @param iV8ValueArray the V8 value array + * @param v8Values the V8 values + * @param startIndex the start index + * @param endIndex the end index * @return the actual item count * @throws JavetException the javet exception * @since 2.2.0 */ @SuppressWarnings("RedundantThrows") int batchArrayGet( - IV8ValueSealedArray iV8ValueSealedArray, V8Value[] v8Values, int startIndex, int endIndex) + IV8ValueArray iV8ValueArray, V8Value[] v8Values, int startIndex, int endIndex) throws JavetException { return v8Native.batchArrayGet( - handle, iV8ValueSealedArray.getHandle(), iV8ValueSealedArray.getType().getId(), + handle, iV8ValueArray.getHandle(), iV8ValueArray.getType().getId(), v8Values, startIndex, endIndex); } @@ -2654,6 +2654,17 @@ T objectInvoke( return (T) result; } + /** + * Object is sealed. + * + * @param iV8ValueObject the V8 value object + * @return true : yes, false: no + * @since 3.1.3 + */ + public boolean objectIsSealed(IV8ValueObject iV8ValueObject) { + return v8Native.objectIsSealed(handle, Objects.requireNonNull(iV8ValueObject).getHandle()); + } + /** * Sets a property of an object by a key * @@ -2666,7 +2677,11 @@ T objectInvoke( @SuppressWarnings("RedundantThrows") boolean objectSet(IV8ValueObject iV8ValueObject, V8Value... v8Values) throws JavetException { assert v8Values.length > 0 && v8Values.length % 2 == 0 : ERROR_THE_KEY_VALUE_PAIR_MUST_MATCH; - return v8Native.objectSet(handle, iV8ValueObject.getHandle(), iV8ValueObject.getType().getId(), v8Values); + return v8Native.objectSet( + handle, + Objects.requireNonNull(iV8ValueObject).getHandle(), + iV8ValueObject.getType().getId(), + v8Values); } /** 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 c4c9274f2..24a704481 100644 --- a/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java +++ b/src/main/java/com/caoccao/javet/interop/converters/JavetObjectConverter.java @@ -208,12 +208,7 @@ protected T toObject(V8Value v8Value, final int depth) throws JavetException V8ValueArray v8ValueArray = (V8ValueArray) v8Value; final List list = new ArrayList<>(); v8ValueArray.forEach(value -> list.add(toObject(value, depth + 1))); - return (T) list; - } else if (v8Value instanceof V8ValueSealedArray) { - V8ValueSealedArray v8ValueSealedArray = (V8ValueSealedArray) v8Value; - final List list = new ArrayList<>(); - v8ValueSealedArray.forEach(value -> list.add(toObject(value, depth + 1))); - return (T) list.toArray(); + return (T) (v8ValueArray.isSealed() ? list.toArray() : list); } else if (v8Value instanceof V8ValueSet) { V8ValueSet v8ValueSet = (V8ValueSet) v8Value; final HashSet set = new HashSet<>(); diff --git a/src/main/java/com/caoccao/javet/values/reference/IV8ValueArray.java b/src/main/java/com/caoccao/javet/values/reference/IV8ValueArray.java index f5fac9510..6257b3675 100644 --- a/src/main/java/com/caoccao/javet/values/reference/IV8ValueArray.java +++ b/src/main/java/com/caoccao/javet/values/reference/IV8ValueArray.java @@ -37,7 +37,13 @@ * @since 0.7.0 */ @SuppressWarnings("unchecked") -public interface IV8ValueArray extends IV8ValueSealedArray { +public interface IV8ValueArray extends IV8ValueObject { + /** + * The constant FUNCTION_FLAT. + * + * @since 3.0.4 + */ + String FUNCTION_FLAT = "flat"; /** * The constant FUNCTION_SHIFT. * @@ -63,6 +69,134 @@ public interface IV8ValueArray extends IV8ValueSealedArray { */ String FUNCTION_PUSH = "push"; + /** + * Batch get the given range of items from the array. + * + * @param v8Values the V8 values + * @param startIndex the start index + * @param endIndex the end index + * @return the actual item count + * @throws JavetException the javet exception + * @since 2.2.0 + */ + int batchGet(V8Value[] v8Values, int startIndex, int endIndex) throws JavetException; + + /** + * Batch get all the items from the array. + * + * @param the type parameter + * @return the V8 values + * @throws JavetException the javet exception + * @since 2.2.0 + */ + default T[] batchGet() throws JavetException { + final int length = getLength(); + V8Value[] v8Values = new V8Value[length]; + if (length > 0) { + try { + batchGet(v8Values, 0, length); + } catch (Throwable t) { + JavetResourceUtils.safeClose(v8Values); + Arrays.fill(v8Values, null); + throw t; + } + } + return (T[]) v8Values; + } + + /** + * Array.prototype.flat(). + * The flat() method of Array instances creates a new array with all sub-array elements concatenated + * into it recursively up to the default depth 1. + * + * @return the V8 value array + * @throws JavetException the javet exception + * @since 3.0.4 + */ + @CheckReturnValue + default IV8ValueArray flat() throws JavetException { + return invoke(FUNCTION_FLAT); + } + + /** + * Array.prototype.flat(). + * The flat() method of Array instances creates a new array with all sub-array elements concatenated + * into it recursively up to the specified depth. + * + * @param depth the depth level specifying how deep a nested array structure should be flattened. Defaults to 1. + * @return the V8 value array + * @throws JavetException the javet exception + * @since 3.0.4 + */ + @CheckReturnValue + default IV8ValueArray flat(int depth) throws JavetException { + return invoke(FUNCTION_FLAT, getV8Runtime().createV8ValueInteger(depth)); + } + + /** + * For each of the item, call the consumer and return the item count. + * + * @param the type parameter + * @param the type parameter + * @param consumer the consumer + * @param batchSize the batch size + * @return the item count + * @throws JavetException the javet exception + * @throws E the custom exception + * @since 2.2.0 + */ + int forEach( + IJavetUniConsumer consumer, + int batchSize) + throws JavetException, E; + + /** + * For each of the item, call the consumer and return the item count. + * + * @param the type parameter + * @param the type parameter + * @param consumer the consumer + * @param batchSize the batch size + * @return the item count + * @throws JavetException the javet exception + * @throws E the custom exception + * @since 2.2.0 + */ + int forEach( + IJavetUniIndexedConsumer consumer, + int batchSize) + throws JavetException, E; + + /** + * Get V8 value by index. + * + * @param the type parameter + * @param index the index + * @return the V8 value + * @throws JavetException the javet exception + * @since 0.7.0 + */ + @CheckReturnValue + T get(int index) throws JavetException; + + /** + * Gets keys. + * + * @return the keys + * @throws JavetException the javet exception + * @since 0.7.2 + */ + List getKeys() throws JavetException; + + /** + * Gets length. + * + * @return the length + * @throws JavetException the javet exception + * @since 0.7.0 + */ + int getLength() throws JavetException; + /** * Array.prototype.pop(). * The pop() method of Array instances removes the last element from an array and returns that element. @@ -401,6 +535,18 @@ default ZonedDateTime shiftZonedDateTime() throws JavetException { return shiftPrimitive(); } + /** + * To V8 value array. + * + * @return the V8 value array + * @throws JavetException the javet exception + * @since 0.9.10 + */ + @CheckReturnValue + default V8Value[] toArray() throws JavetException { + return batchGet(); + } + /** * Array.prototype.unshift(). * The unshift() method of Array instances adds the specified elements to the beginning of an array diff --git a/src/main/java/com/caoccao/javet/values/reference/IV8ValueObject.java b/src/main/java/com/caoccao/javet/values/reference/IV8ValueObject.java index 9331e3046..d7165d5e3 100644 --- a/src/main/java/com/caoccao/javet/values/reference/IV8ValueObject.java +++ b/src/main/java/com/caoccao/javet/values/reference/IV8ValueObject.java @@ -1227,6 +1227,15 @@ default boolean isGeneratorObject() throws JavetException { return hasInternalType(V8ValueInternalType.GeneratorObject); } + /** + * Is sealed. + * + * @return true : yes, false: no + * @throws JavetException the javet exception + * @since 3.1.3 + */ + boolean isSealed() throws JavetException; + /** * Set property by key object and value object. * diff --git a/src/main/java/com/caoccao/javet/values/reference/IV8ValueSealedArray.java b/src/main/java/com/caoccao/javet/values/reference/IV8ValueSealedArray.java deleted file mode 100644 index 0053045d3..000000000 --- a/src/main/java/com/caoccao/javet/values/reference/IV8ValueSealedArray.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2021-2024. 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.annotations.CheckReturnValue; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interfaces.IJavetUniConsumer; -import com.caoccao.javet.interfaces.IJavetUniIndexedConsumer; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.values.V8Value; - -import java.util.Arrays; -import java.util.List; - -/** - * The interface V8 value array. - * - * @since 3.1.3 - */ -@SuppressWarnings("unchecked") -public interface IV8ValueSealedArray extends IV8ValueObject { - /** - * The constant FUNCTION_FLAT. - * - * @since 3.1.3 - */ - String FUNCTION_FLAT = "flat"; - - /** - * Batch get the given range of items from the array. - * - * @param v8Values the V8 values - * @param startIndex the start index - * @param endIndex the end index - * @return the actual item count - * @throws JavetException the javet exception - * @since 3.1.3 - */ - int batchGet(V8Value[] v8Values, int startIndex, int endIndex) throws JavetException; - - /** - * Batch get all the items from the array. - * - * @param the type parameter - * @return the V8 values - * @throws JavetException the javet exception - * @since 3.1.3 - */ - default T[] batchGet() throws JavetException { - final int length = getLength(); - V8Value[] v8Values = new V8Value[length]; - if (length > 0) { - try { - batchGet(v8Values, 0, length); - } catch (Throwable t) { - JavetResourceUtils.safeClose(v8Values); - Arrays.fill(v8Values, null); - throw t; - } - } - return (T[]) v8Values; - } - - /** - * Array.prototype.flat(). - * The flat() method of Array instances creates a new array with all sub-array elements concatenated - * into it recursively up to the default depth 1. - * - * @return the V8 value array - * @throws JavetException the javet exception - * @since 3.1.3 - */ - @CheckReturnValue - default IV8ValueSealedArray flat() throws JavetException { - return invoke(FUNCTION_FLAT); - } - - /** - * Array.prototype.flat(). - * The flat() method of Array instances creates a new array with all sub-array elements concatenated - * into it recursively up to the specified depth. - * - * @param depth the depth level specifying how deep a nested array structure should be flattened. Defaults to 1. - * @return the V8 value array - * @throws JavetException the javet exception - * @since 3.1.3 - */ - @CheckReturnValue - default IV8ValueSealedArray flat(int depth) throws JavetException { - return invoke(FUNCTION_FLAT, getV8Runtime().createV8ValueInteger(depth)); - } - - /** - * For each of the item, call the consumer and return the item count. - * - * @param the type parameter - * @param the type parameter - * @param consumer the consumer - * @param batchSize the batch size - * @return the item count - * @throws JavetException the javet exception - * @throws E the custom exception - * @since 3.1.3 - */ - int forEach( - IJavetUniConsumer consumer, - int batchSize) - throws JavetException, E; - - /** - * For each of the item, call the consumer and return the item count. - * - * @param the type parameter - * @param the type parameter - * @param consumer the consumer - * @param batchSize the batch size - * @return the item count - * @throws JavetException the javet exception - * @throws E the custom exception - * @since 3.1.3 - */ - int forEach( - IJavetUniIndexedConsumer consumer, - int batchSize) - throws JavetException, E; - - /** - * Get V8 value by index. - * - * @param the type parameter - * @param index the index - * @return the V8 value - * @throws JavetException the javet exception - * @since 3.1.3 - */ - @CheckReturnValue - T get(int index) throws JavetException; - - /** - * Gets keys. - * - * @return the keys - * @throws JavetException the javet exception - * @since 3.1.3 - */ - List getKeys() throws JavetException; - - /** - * Gets length. - * - * @return the length - * @throws JavetException the javet exception - * @since 3.1.3 - */ - int getLength() throws JavetException; - - /** - * To V8 value array. - * - * @return the V8 value array - * @throws JavetException the javet exception - * @since 3.1.3 - */ - @CheckReturnValue - default V8Value[] toArray() throws JavetException { - return batchGet(); - } -} diff --git a/src/main/java/com/caoccao/javet/values/reference/V8ValueArray.java b/src/main/java/com/caoccao/javet/values/reference/V8ValueArray.java index 348387771..24df53092 100644 --- a/src/main/java/com/caoccao/javet/values/reference/V8ValueArray.java +++ b/src/main/java/com/caoccao/javet/values/reference/V8ValueArray.java @@ -16,20 +16,148 @@ package com.caoccao.javet.values.reference; +import com.caoccao.javet.annotations.CheckReturnValue; import com.caoccao.javet.enums.V8ValueReferenceType; import com.caoccao.javet.exceptions.JavetException; +import com.caoccao.javet.interfaces.IJavetUniConsumer; +import com.caoccao.javet.interfaces.IJavetUniIndexedConsumer; import com.caoccao.javet.interop.V8Runtime; +import com.caoccao.javet.utils.JavetResourceUtils; +import com.caoccao.javet.values.V8Value; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; /** * The type V8 value array. * * @since 0.7.0 */ -public class V8ValueArray extends V8ValueSealedArray implements IV8ValueArray { +@SuppressWarnings("unchecked") +public class V8ValueArray extends V8ValueObject implements IV8ValueArray { + protected static final String FUNCTION_KEYS = "keys"; + protected static final String FUNCTION_NEXT = "next"; + protected static final String PROPERTY_DONE = "done"; + protected static final String PROPERTY_VALUE = "value"; + V8ValueArray(V8Runtime v8Runtime, long handle) throws JavetException { super(v8Runtime, handle); } + @Override + public int asInt() throws JavetException { + if (getLength() == 1) { + try (V8Value v8Value = get(0)) { + return v8Value.asInt(); + } + } + return 0; + } + + @Override + public int batchGet(V8Value[] v8Values, int startIndex, int endIndex) throws JavetException { + return checkV8Runtime().getV8Internal().batchArrayGet(this, v8Values, startIndex, endIndex); + } + + @Override + public int forEach( + IJavetUniConsumer consumer) + throws JavetException, E { + return forEach(consumer, DEFAULT_BATCH_SIZE); + } + + @Override + public int forEach( + IJavetUniConsumer consumer, + int batchSize) + throws JavetException, E { + Objects.requireNonNull(consumer); + batchSize = Math.max(MIN_BATCH_SIZE, batchSize); + final int length = getLength(); + if (length > 0) { + V8Value[] v8Values = new V8Value[batchSize]; + final int loopCount = (length + batchSize - 1) / batchSize; + for (int i = 0; i < loopCount; i++) { + final int startIndex = i * batchSize; + final int endIndex = i == loopCount - 1 ? length : startIndex + batchSize; + try { + int actualLength = batchGet(v8Values, startIndex, endIndex); + for (int j = 0; j < actualLength; j++) { + consumer.accept((Value) v8Values[j]); + } + } finally { + JavetResourceUtils.safeClose(v8Values); + Arrays.fill(v8Values, null); + } + } + } + return length; + } + + @Override + public int forEach( + IJavetUniIndexedConsumer consumer) + throws JavetException, E { + return forEach(consumer, DEFAULT_BATCH_SIZE); + } + + @Override + public int forEach( + IJavetUniIndexedConsumer consumer, + int batchSize) + throws JavetException, E { + Objects.requireNonNull(consumer); + batchSize = Math.max(MIN_BATCH_SIZE, batchSize); + final int length = getLength(); + if (length > 0) { + V8Value[] v8Values = new V8Value[batchSize]; + final int loopCount = (length + batchSize - 1) / batchSize; + for (int i = 0; i < loopCount; i++) { + final int startIndex = i * batchSize; + final int endIndex = i == loopCount - 1 ? length : startIndex + batchSize; + try { + int actualLength = batchGet(v8Values, startIndex, endIndex); + for (int j = 0; j < actualLength; j++) { + consumer.accept(startIndex + j, (Value) v8Values[j]); + } + } finally { + JavetResourceUtils.safeClose(v8Values); + Arrays.fill(v8Values, null); + } + } + } + return length; + } + + @Override + @CheckReturnValue + public T get(int index) throws JavetException { + return checkV8Runtime().getV8Internal().objectGet(this, v8Runtime.createV8ValueInteger(index)); + } + + @Override + public List getKeys() throws JavetException { + try (V8ValueObject iterator = invoke(FUNCTION_KEYS)) { + List keys = new ArrayList<>(); + while (true) { + try (V8ValueObject next = iterator.invoke(FUNCTION_NEXT)) { + if (next.getBoolean(PROPERTY_DONE)) { + break; + } + keys.add(next.getInteger(PROPERTY_VALUE)); + } + } + return keys; + } + } + + @Override + public int getLength() throws JavetException { + return checkV8Runtime().getV8Internal().arrayGetLength(this); + } + @Override public V8ValueReferenceType getType() { return V8ValueReferenceType.Array; 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 97cf44a00..536a1308c 100644 --- a/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java +++ b/src/main/java/com/caoccao/javet/values/reference/V8ValueObject.java @@ -604,6 +604,11 @@ public T invokeExtended(String functionName, boolean returnR return checkV8Runtime().getV8Internal().objectInvoke(this, functionName, returnResult, v8Values); } + @Override + public boolean isSealed() throws JavetException { + return checkV8Runtime().getV8Internal().objectIsSealed(this); + } + @Override public boolean sameValue(V8Value v8Value) throws JavetException { if (!(v8Value instanceof V8ValueObject)) { diff --git a/src/main/java/com/caoccao/javet/values/reference/V8ValueSealedArray.java b/src/main/java/com/caoccao/javet/values/reference/V8ValueSealedArray.java deleted file mode 100644 index d7fb1ea2f..000000000 --- a/src/main/java/com/caoccao/javet/values/reference/V8ValueSealedArray.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2021-2024. 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.annotations.CheckReturnValue; -import com.caoccao.javet.enums.V8ValueReferenceType; -import com.caoccao.javet.exceptions.JavetException; -import com.caoccao.javet.interfaces.IJavetUniConsumer; -import com.caoccao.javet.interfaces.IJavetUniIndexedConsumer; -import com.caoccao.javet.interop.V8Runtime; -import com.caoccao.javet.utils.JavetResourceUtils; -import com.caoccao.javet.values.V8Value; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * The type V8 value sealed array. - * - * @since 3.1.3 - */ -@SuppressWarnings("unchecked") -public class V8ValueSealedArray extends V8ValueObject implements IV8ValueSealedArray { - protected static final String FUNCTION_KEYS = "keys"; - protected static final String FUNCTION_NEXT = "next"; - protected static final String PROPERTY_DONE = "done"; - protected static final String PROPERTY_VALUE = "value"; - - V8ValueSealedArray(V8Runtime v8Runtime, long handle) throws JavetException { - super(v8Runtime, handle); - } - - @Override - public int asInt() throws JavetException { - if (getLength() == 1) { - try (V8Value v8Value = get(0)) { - return v8Value.asInt(); - } - } - return 0; - } - - @Override - public int batchGet(V8Value[] v8Values, int startIndex, int endIndex) throws JavetException { - return checkV8Runtime().getV8Internal().batchArrayGet(this, v8Values, startIndex, endIndex); - } - - @Override - public int forEach( - IJavetUniConsumer consumer) - throws JavetException, E { - return forEach(consumer, DEFAULT_BATCH_SIZE); - } - - @Override - public int forEach( - IJavetUniConsumer consumer, - int batchSize) - throws JavetException, E { - Objects.requireNonNull(consumer); - batchSize = Math.max(MIN_BATCH_SIZE, batchSize); - final int length = getLength(); - if (length > 0) { - V8Value[] v8Values = new V8Value[batchSize]; - final int loopCount = (length + batchSize - 1) / batchSize; - for (int i = 0; i < loopCount; i++) { - final int startIndex = i * batchSize; - final int endIndex = i == loopCount - 1 ? length : startIndex + batchSize; - try { - int actualLength = batchGet(v8Values, startIndex, endIndex); - for (int j = 0; j < actualLength; j++) { - consumer.accept((Value) v8Values[j]); - } - } finally { - JavetResourceUtils.safeClose(v8Values); - Arrays.fill(v8Values, null); - } - } - } - return length; - } - - @Override - public int forEach( - IJavetUniIndexedConsumer consumer) - throws JavetException, E { - return forEach(consumer, DEFAULT_BATCH_SIZE); - } - - @Override - public int forEach( - IJavetUniIndexedConsumer consumer, - int batchSize) - throws JavetException, E { - Objects.requireNonNull(consumer); - batchSize = Math.max(MIN_BATCH_SIZE, batchSize); - final int length = getLength(); - if (length > 0) { - V8Value[] v8Values = new V8Value[batchSize]; - final int loopCount = (length + batchSize - 1) / batchSize; - for (int i = 0; i < loopCount; i++) { - final int startIndex = i * batchSize; - final int endIndex = i == loopCount - 1 ? length : startIndex + batchSize; - try { - int actualLength = batchGet(v8Values, startIndex, endIndex); - for (int j = 0; j < actualLength; j++) { - consumer.accept(startIndex + j, (Value) v8Values[j]); - } - } finally { - JavetResourceUtils.safeClose(v8Values); - Arrays.fill(v8Values, null); - } - } - } - return length; - } - - @Override - @CheckReturnValue - public T get(int index) throws JavetException { - return checkV8Runtime().getV8Internal().objectGet(this, v8Runtime.createV8ValueInteger(index)); - } - - @Override - public List getKeys() throws JavetException { - try (V8ValueObject iterator = invoke(FUNCTION_KEYS)) { - List keys = new ArrayList<>(); - while (true) { - try (V8ValueObject next = iterator.invoke(FUNCTION_NEXT)) { - if (next.getBoolean(PROPERTY_DONE)) { - break; - } - keys.add(next.getInteger(PROPERTY_VALUE)); - } - } - return keys; - } - } - - @Override - public int getLength() throws JavetException { - return checkV8Runtime().getV8Internal().arrayGetLength(this); - } - - @Override - public V8ValueReferenceType getType() { - return V8ValueReferenceType.Array; - } -} 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 6ff44b2b7..a7b052ada 100644 --- a/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java +++ b/src/test/java/com/caoccao/javet/interop/converters/TestJavetObjectConverter.java @@ -89,6 +89,7 @@ public void testAnonymousFunction() throws JavetException { public void testArray() throws JavetException { IJavetConverter converter = new JavetObjectConverter(); try (V8ValueArray v8ValueArray = v8Runtime.createV8ValueArray()) { + assertFalse(v8ValueArray.isSealed()); v8ValueArray.push("abc"); v8ValueArray.push(123); List list = converter.toObject(v8ValueArray); @@ -133,6 +134,19 @@ public void testArray() throws JavetException { assertEquals(1, v8ValueArray.getInteger(0)); assertEquals("abc", v8ValueArray.getString(1)); } + // Sealed + try (V8ValueArray v8ValueArray = v8Runtime.getExecutor("Object.seal([1,2])").execute()) { + assertTrue(v8ValueArray.isSealed()); + } + assertArrayEquals( + new Object[]{1, 2}, + v8Runtime.getExecutor("Object.seal([1,2])").executeObject()); + assertArrayEquals( + new Object[]{"a", "b"}, + v8Runtime.getExecutor("Object.seal(['a','b'])").executeObject()); + assertArrayEquals( + new Object[]{}, + v8Runtime.getExecutor("Object.seal([])").executeObject()); } @Test @@ -255,19 +269,6 @@ public void testObject() throws JavetException { } } - @Test - public void testSealedArray() throws JavetException { - assertArrayEquals( - new Object[]{1, 2}, - v8Runtime.getExecutor("Object.seal([1,2])").executeObject()); - assertArrayEquals( - new Object[]{"a", "b"}, - v8Runtime.getExecutor("Object.seal(['a','b'])").executeObject()); - assertArrayEquals( - new Object[]{}, - v8Runtime.getExecutor("Object.seal([])").executeObject()); - } - @Test public void testSet() throws JavetException { IJavetConverter converter = new JavetObjectConverter(); diff --git a/src/test/java/com/caoccao/javet/values/reference/TestV8ValueObject.java b/src/test/java/com/caoccao/javet/values/reference/TestV8ValueObject.java index d20427507..34abb3428 100644 --- a/src/test/java/com/caoccao/javet/values/reference/TestV8ValueObject.java +++ b/src/test/java/com/caoccao/javet/values/reference/TestV8ValueObject.java @@ -529,6 +529,16 @@ public void testPrototype() throws JavetException { assertEquals(2, v8Runtime.getExecutor("b.b();").executeInteger()); } + @Test + public void testSeal() throws JavetException { + try (V8ValueObject v8ValueObject = v8Runtime.getExecutor("const a = {}; a;").execute()) { + assertFalse(v8ValueObject.isSealed()); + } + try (V8ValueObject v8ValueObject = v8Runtime.getExecutor("const b = {}; Object.seal(b);").execute()) { + assertTrue(v8ValueObject.isSealed()); + } + } + @Test public void testSetProperty() throws JavetException { ZonedDateTime now = ZonedDateTime.now(); diff --git a/src/test/java/com/caoccao/javet/values/reference/TestV8ValueSealedArray.java b/src/test/java/com/caoccao/javet/values/reference/TestV8ValueSealedArray.java deleted file mode 100644 index 472490dd1..000000000 --- a/src/test/java/com/caoccao/javet/values/reference/TestV8ValueSealedArray.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2021-2024. 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.JavetException; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; - -public class TestV8ValueSealedArray extends BaseTestJavetRuntime { - @Test - public void testConversion() throws JavetException { - assertArrayEquals( - new Object[]{1, 2}, - v8Runtime.getExecutor("Object.seal([1,2])").executeObject()); - assertArrayEquals( - new Object[]{"a", "b"}, - v8Runtime.getExecutor("Object.seal(['a','b'])").executeObject()); - assertArrayEquals( - new Object[]{}, - v8Runtime.getExecutor("Object.seal([])").executeObject()); - } -}