com.caoccao.javet.values.reference.V8ValueObject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javet-linux-arm64 Show documentation
Show all versions of javet-linux-arm64 Show documentation
Javet is Java + V8 (JAVa + V + EighT). It is an awesome way of embedding Node.js and V8 in Java.
/*
* 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.*;
import com.caoccao.javet.enums.V8ValueInternalType;
import com.caoccao.javet.enums.V8ValueReferenceType;
import com.caoccao.javet.enums.V8ValueSymbolType;
import com.caoccao.javet.exceptions.JavetError;
import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interfaces.IJavetBiConsumer;
import com.caoccao.javet.interfaces.IJavetBiIndexedConsumer;
import com.caoccao.javet.interop.V8Runtime;
import com.caoccao.javet.interop.binding.BindingContext;
import com.caoccao.javet.interop.binding.BindingContextStore;
import com.caoccao.javet.interop.binding.MethodDescriptor;
import com.caoccao.javet.interop.callback.IJavetDirectCallable;
import com.caoccao.javet.interop.callback.JavetCallbackContext;
import com.caoccao.javet.utils.ArrayUtils;
import com.caoccao.javet.utils.JavetResourceUtils;
import com.caoccao.javet.utils.SimpleMap;
import com.caoccao.javet.values.V8Value;
import com.caoccao.javet.values.primitive.V8ValueString;
import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInJson;
import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInSymbol;
import com.caoccao.javet.values.virtual.V8VirtualValue;
import com.caoccao.javet.values.virtual.V8VirtualValueList;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* The type V8 value object.
*
* @since 0.7.0
*/
@SuppressWarnings("unchecked")
public class V8ValueObject extends V8ValueReference implements IV8ValueObject {
public static final String METHOD_PREFIX_GET = "get";
public static final String METHOD_PREFIX_IS = "is";
public static final String METHOD_PREFIX_SET = "set";
/**
* The constant ERROR_THE_KEY_VALUE_PAIR_MUST_MATCH.
*
* @since 2.2.0
*/
protected static final String ERROR_THE_KEY_VALUE_PAIR_MUST_MATCH = "The key value pair must match.";
protected static final String FUNCTION_ADD = "add";
protected static final String FUNCTION_DELETE = "delete";
protected static final String FUNCTION_GET = "get";
protected static final String FUNCTION_HAS = "has";
protected static final String FUNCTION_SET = "set";
protected static final String PROPERTY_PROTOTYPE = "prototype";
/**
* Instantiates a new V8 value object.
*
* @param v8Runtime the V8 runtime
* @param handle the handle
* @throws JavetException the javet exception
* @since 1.0.7
*/
protected V8ValueObject(V8Runtime v8Runtime, long handle) throws JavetException {
super(v8Runtime, handle);
}
@Override
public int batchGet(V8Value[] v8ValueKeys, V8Value[] v8ValueValues, int length) throws JavetException {
return checkV8Runtime().getV8Internal().batchObjectGet(this, v8ValueKeys, v8ValueValues, length);
}
@Override
public List bind(Object callbackReceiver) throws JavetException {
Objects.requireNonNull(callbackReceiver);
checkV8Runtime();
List javetCallbackContexts = new ArrayList<>();
if (callbackReceiver instanceof IJavetDirectCallable) {
IJavetDirectCallable javetDirectCallable = (IJavetDirectCallable) callbackReceiver;
javetDirectCallable.setV8Runtime(v8Runtime);
JavetCallbackContext[] contexts = javetDirectCallable.getCallbackContexts();
if (contexts != null && contexts.length > 0) {
Map getterMap = new HashMap<>();
Map setterMap = new HashMap<>();
for (JavetCallbackContext javetCallbackContext : contexts) {
switch (javetCallbackContext.getCallbackType()) {
case DirectCallGetterAndNoThis:
case DirectCallGetterAndThis:
getterMap.put(javetCallbackContext.getName(), javetCallbackContext);
break;
case DirectCallSetterAndNoThis:
case DirectCallSetterAndThis:
setterMap.put(javetCallbackContext.getName(), javetCallbackContext);
break;
default:
javetCallbackContexts.add(javetCallbackContext);
bindFunction(javetCallbackContext);
break;
}
}
for (JavetCallbackContext javetCallbackContextGetter : getterMap.values()) {
JavetCallbackContext javetCallbackContextSetter = setterMap.get(javetCallbackContextGetter.getName());
javetCallbackContexts.add(javetCallbackContextGetter);
if (javetCallbackContextSetter != null) {
javetCallbackContexts.add(javetCallbackContextSetter);
}
bindProperty(javetCallbackContextGetter, javetCallbackContextSetter);
}
}
} else {
BindingContext bindingContext = getBindingContext(callbackReceiver.getClass());
Map propertyGetterMap = bindingContext.getPropertyGetterMap();
Map propertySetterMap = bindingContext.getPropertySetterMap();
Map functionMap = bindingContext.getFunctionMap();
Method v8BindingEnabler = bindingContext.getV8BindingEnabler();
Method v8RuntimeSetter = bindingContext.getV8RuntimeSetter();
if (v8RuntimeSetter != null) {
try {
v8RuntimeSetter.invoke(callbackReceiver, getV8Runtime());
} catch (Exception e) {
throw new JavetException(
JavetError.CallbackInjectionFailure,
SimpleMap.of(JavetError.PARAMETER_MESSAGE, e.getMessage()),
e);
}
}
if (!propertyGetterMap.isEmpty()) {
for (Map.Entry entry : propertyGetterMap.entrySet()) {
String propertyName = entry.getKey();
final MethodDescriptor getterMethodDescriptor = entry.getValue();
try {
if (v8BindingEnabler != null && !(boolean) v8BindingEnabler.invoke(
callbackReceiver, getterMethodDescriptor.getMethod().getName())) {
continue;
}
// Static method needs to be identified.
JavetCallbackContext javetCallbackContextGetter = new JavetCallbackContext(
propertyName,
getterMethodDescriptor.getSymbolType(),
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);
if (v8BindingEnabler != null && !(boolean) v8BindingEnabler.invoke(
callbackReceiver, setterMethodDescriptor.getMethod().getName())) {
continue;
}
// Static method needs to be identified.
javetCallbackContextSetter = new JavetCallbackContext(
propertyName,
setterMethodDescriptor.getSymbolType(),
Modifier.isStatic(setterMethodDescriptor.getMethod().getModifiers()) ? null : callbackReceiver,
setterMethodDescriptor.getMethod(), setterMethodDescriptor.isThisObjectRequired());
javetCallbackContexts.add(javetCallbackContextSetter);
}
bindProperty(javetCallbackContextGetter, javetCallbackContextSetter);
} catch (Exception e) {
throw new JavetException(
JavetError.CallbackRegistrationFailure,
SimpleMap.of(
JavetError.PARAMETER_METHOD_NAME, getterMethodDescriptor.getMethod().getName(),
JavetError.PARAMETER_MESSAGE, e.getMessage()),
e);
}
}
}
if (!functionMap.isEmpty()) {
for (Map.Entry entry : functionMap.entrySet()) {
String functionName = entry.getKey();
final MethodDescriptor functionMethodDescriptor = entry.getValue();
try {
if (v8BindingEnabler != null && !(boolean) v8BindingEnabler.invoke(
callbackReceiver, functionMethodDescriptor.getMethod().getName())) {
continue;
}
// Static method needs to be identified.
JavetCallbackContext javetCallbackContext = new JavetCallbackContext(
functionName,
functionMethodDescriptor.getSymbolType(),
Modifier.isStatic(functionMethodDescriptor.getMethod().getModifiers()) ?
null : callbackReceiver,
functionMethodDescriptor.getMethod(), functionMethodDescriptor.isThisObjectRequired());
javetCallbackContexts.add(javetCallbackContext);
bindFunction(javetCallbackContext);
} catch (Exception e) {
throw new JavetException(
JavetError.CallbackRegistrationFailure,
SimpleMap.of(
JavetError.PARAMETER_METHOD_NAME, functionMethodDescriptor.getMethod().getName(),
JavetError.PARAMETER_MESSAGE, e.getMessage()),
e);
}
}
}
}
return javetCallbackContexts;
}
@Override
public boolean bindFunction(JavetCallbackContext javetCallbackContext) throws JavetException {
String functionName = Objects.requireNonNull(javetCallbackContext).getName();
switch (javetCallbackContext.getSymbolType()) {
case BuiltIn:
try (V8ValueBuiltInSymbol v8ValueBuiltInSymbol = v8Runtime.getGlobalObject().getBuiltInSymbol();
V8ValueSymbol v8ValueSymbol = v8ValueBuiltInSymbol.getBuiltInSymbol(functionName)) {
if (v8ValueSymbol == null) {
throw new JavetException(
JavetError.ConverterSymbolNotBuiltIn,
SimpleMap.of(JavetError.PARAMETER_SYMBOL, functionName));
}
try (V8ValueFunction v8ValueFunction =
checkV8Runtime().createV8ValueFunction(javetCallbackContext)) {
return set(v8ValueSymbol, v8ValueFunction);
}
}
case Custom:
try (V8ValueSymbol v8ValueSymbol = v8Runtime.createV8ValueSymbol(functionName, true);
V8ValueFunction v8ValueFunction = checkV8Runtime().createV8ValueFunction(javetCallbackContext)) {
return set(v8ValueSymbol, v8ValueFunction);
}
default:
try (V8ValueFunction v8ValueFunction = checkV8Runtime().createV8ValueFunction(javetCallbackContext)) {
return set(functionName, v8ValueFunction);
}
}
}
@Override
public boolean bindProperty(
JavetCallbackContext javetCallbackContextGetter,
JavetCallbackContext javetCallbackContextSetter)
throws JavetException {
String propertyName = Objects.requireNonNull(javetCallbackContextGetter).getName();
switch (javetCallbackContextGetter.getSymbolType()) {
case BuiltIn:
try (V8ValueBuiltInSymbol v8ValueBuiltInSymbol = v8Runtime.getGlobalObject().getBuiltInSymbol();
V8ValueSymbol v8ValueSymbol = v8ValueBuiltInSymbol.getBuiltInSymbol(propertyName)) {
if (v8ValueSymbol == null) {
throw new JavetException(
JavetError.ConverterSymbolNotBuiltIn,
SimpleMap.of(JavetError.PARAMETER_SYMBOL, propertyName));
}
return checkV8Runtime().getV8Internal().objectSetAccessor(
this, v8ValueSymbol, javetCallbackContextGetter, javetCallbackContextSetter);
}
case Custom:
try (V8ValueSymbol v8ValueSymbol = v8Runtime.createV8ValueSymbol(propertyName, true)) {
return checkV8Runtime().getV8Internal().objectSetAccessor(
this, v8ValueSymbol, javetCallbackContextGetter, javetCallbackContextSetter);
}
default:
try (V8ValueString v8ValueString = v8Runtime.createV8ValueString(propertyName)) {
return checkV8Runtime().getV8Internal().objectSetAccessor(
this, v8ValueString, javetCallbackContextGetter, javetCallbackContextSetter);
}
}
}
@Override
public boolean delete(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectDelete(this, virtualKey.get());
}
}
@Override
public boolean deletePrivateProperty(String propertyName) throws JavetException {
return checkV8Runtime().getV8Internal().objectDeletePrivateProperty(
this, Objects.requireNonNull(propertyName));
}
@Override
public int forEach(
IJavetBiConsumer consumer,
int batchSize)
throws JavetException, E {
Objects.requireNonNull(consumer);
try (IV8ValueArray iV8ValueArray = getOwnPropertyNames()) {
batchSize = Math.max(MIN_BATCH_SIZE, batchSize);
final int length = iV8ValueArray.getLength();
if (length > 0) {
V8Value[] v8ValueKeys = new V8Value[batchSize];
V8Value[] v8ValueValues = 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 = iV8ValueArray.batchGet(v8ValueKeys, startIndex, endIndex);
if (actualLength > 0) {
batchGet(v8ValueKeys, v8ValueValues, actualLength);
for (int j = 0; j < actualLength; j++) {
consumer.accept((Key) v8ValueKeys[j], (Value) v8ValueValues[j]);
}
}
} finally {
JavetResourceUtils.safeClose(v8ValueKeys);
JavetResourceUtils.safeClose(v8ValueValues);
Arrays.fill(v8ValueKeys, null);
Arrays.fill(v8ValueValues, null);
}
}
}
return length;
}
}
@Override
public int forEach(
IJavetBiIndexedConsumer consumer,
int batchSize)
throws JavetException, E {
Objects.requireNonNull(consumer);
try (IV8ValueArray iV8ValueArray = getOwnPropertyNames()) {
batchSize = Math.max(MIN_BATCH_SIZE, batchSize);
final int length = iV8ValueArray.getLength();
if (length > 0) {
V8Value[] v8ValueKeys = new V8Value[batchSize];
V8Value[] v8ValueValues = 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 = iV8ValueArray.batchGet(v8ValueKeys, startIndex, endIndex);
batchGet(v8ValueKeys, v8ValueValues, actualLength);
for (int j = 0; j < actualLength; j++) {
consumer.accept(startIndex + j, (Key) v8ValueKeys[j], (Value) v8ValueValues[j]);
}
} finally {
JavetResourceUtils.safeClose(v8ValueKeys);
JavetResourceUtils.safeClose(v8ValueValues);
Arrays.fill(v8ValueKeys, null);
Arrays.fill(v8ValueValues, null);
}
}
}
return length;
}
}
@Override
@CheckReturnValue
public T get(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGet(this, virtualKey.get());
}
}
BindingContext getBindingContext(Class> callbackReceiverClass) throws JavetException {
Objects.requireNonNull(callbackReceiverClass);
BindingContext bindingContext = BindingContextStore.getMap().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()) {
boolean methodHandled = false;
if (method.isAnnotationPresent(V8Property.class)) {
V8Property v8Property = method.getAnnotation(V8Property.class);
String propertyName = v8Property.name();
if (propertyName.isEmpty()) {
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());
} else {
propertyName = methodName;
}
if (!propertyName.isEmpty()) {
propertyName = propertyName.substring(0, 1).toLowerCase(Locale.ROOT) + propertyName.substring(1);
}
}
if (!propertyName.isEmpty()) {
final int expectedGetterParameterCount = v8Property.thisObjectRequired() ? 1 : 0;
final int expectedSetterParameterCount = expectedGetterParameterCount + 1;
if (method.getParameterCount() == expectedGetterParameterCount) {
// Duplicated property name will be dropped.
if (!propertyGetterMap.containsKey(propertyName)) {
propertyGetterMap.put(
propertyName,
new MethodDescriptor(method, v8Property.thisObjectRequired(), v8Property.symbolType()));
methodHandled = true;
}
} else if (method.getParameterCount() == expectedSetterParameterCount) {
// Duplicated property name will be dropped.
if (!propertySetterMap.containsKey(propertyName)) {
propertySetterMap.put(
propertyName,
new MethodDescriptor(method, v8Property.thisObjectRequired(), v8Property.symbolType()));
methodHandled = true;
}
} 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()));
}
}
}
if (method.isAnnotationPresent(V8Function.class)) {
V8Function v8Function = method.getAnnotation(V8Function.class);
String functionName = v8Function.name();
if (functionName.isEmpty()) {
functionName = method.getName();
}
// Duplicated function will be dropped.
if (!functionMap.containsKey(functionName)) {
functionMap.put(
functionName,
new MethodDescriptor(method, v8Function.thisObjectRequired()));
methodHandled = true;
}
}
if (!methodHandled) {
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);
} else if (method.isAnnotationPresent(V8BindingEnabler.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 (!String.class.isAssignableFrom(method.getParameterTypes()[0])) {
throw new JavetException(
JavetError.CallbackSignatureParameterTypeMismatch,
SimpleMap.of(
JavetError.PARAMETER_EXPECTED_PARAMETER_TYPE, String.class,
JavetError.PARAMETER_ACTUAL_PARAMETER_TYPE, method.getParameterTypes()[0]));
}
bindingContext.setV8BindingEnabler(method);
}
}
}
BindingContextStore.getMap().put(callbackReceiverClass, bindingContext);
}
return bindingContext;
}
@Override
public Boolean getBoolean(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetBoolean(this, virtualKey.get());
}
}
@Override
public Double getDouble(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetDouble(this, virtualKey.get());
}
}
@Override
public int getIdentityHash() throws JavetException {
return checkV8Runtime().getV8Internal().objectGetIdentityHash(this);
}
@Override
public Integer getInteger(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetInteger(this, virtualKey.get());
}
}
@Override
public Long getLong(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetLong(this, virtualKey.get());
}
}
@Override
@CheckReturnValue
public IV8ValueArray getOwnPropertyNames() throws JavetException {
return checkV8Runtime().getV8Internal().objectGetOwnPropertyNames(this);
}
@Override
public T getPrivateProperty(String propertyName) throws JavetException {
return checkV8Runtime().getV8Internal().objectGetPrivateProperty(
this, Objects.requireNonNull(propertyName));
}
@Override
@CheckReturnValue
public T getProperty(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetProperty(this, virtualKey.get());
}
}
@Override
@CheckReturnValue
public IV8ValueArray getPropertyNames() throws JavetException {
return checkV8Runtime().getV8Internal().objectGetPropertyNames(this);
}
@Override
public T getPrototype() throws JavetException {
return (T) get(PROPERTY_PROTOTYPE);
}
@Override
public String getString(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectGetString(this, virtualKey.get());
}
}
@Override
public V8ValueReferenceType getType() {
return V8ValueReferenceType.Object;
}
@Override
public boolean has(Object value) throws JavetException {
try (V8VirtualValue virtualValue = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(value))) {
return v8Runtime.getV8Internal().objectHas(this, virtualValue.get());
}
}
@Override
public boolean hasInternalType(V8ValueInternalType internalType) throws JavetException {
return checkV8Runtime().getV8Internal().hasInternalType(this, Objects.requireNonNull(internalType));
}
@Override
public boolean hasOwnProperty(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectHasOwnProperty(this, virtualKey.get());
}
}
@Override
public boolean hasPrivateProperty(String propertyName) throws JavetException {
return checkV8Runtime().getV8Internal().objectHasPrivateProperty(
this, Objects.requireNonNull(propertyName));
}
@Override
@CheckReturnValue
public T invokeExtended(String functionName, boolean returnResult, Object... objects)
throws JavetException {
Objects.requireNonNull(functionName);
try (V8VirtualValueList virtualValueList = new V8VirtualValueList(checkV8Runtime(), null, objects)) {
return v8Runtime.getV8Internal().objectInvoke(
this, functionName, returnResult, virtualValueList.get());
}
}
@Override
@CheckReturnValue
public T invokeExtended(String functionName, boolean returnResult, V8Value... v8Values)
throws JavetException {
Objects.requireNonNull(functionName);
return checkV8Runtime().getV8Internal().objectInvoke(this, functionName, returnResult, v8Values);
}
@Override
public boolean isFrozen() throws JavetException {
return checkV8Runtime().getV8Internal().objectIsFrozen(this);
}
@Override
public boolean isSealed() throws JavetException {
return checkV8Runtime().getV8Internal().objectIsSealed(this);
}
@Override
public boolean sameValue(V8Value v8Value) throws JavetException {
if (!(v8Value instanceof V8ValueObject)) {
return false;
}
if (v8Value.getClass() != this.getClass()) {
return false;
}
V8ValueObject v8ValueObject = (V8ValueObject) v8Value;
if (getHandle() == v8ValueObject.getHandle()) {
return true;
}
return checkV8Runtime().getV8Internal().sameValue(this, v8ValueObject);
}
@Override
public boolean set(Object key, Object value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key));
V8VirtualValue virtualValue = new V8VirtualValue(v8Runtime, null, value)) {
return v8Runtime.getV8Internal().objectSet(this, virtualKey.get(), virtualValue.get());
}
}
@Override
public boolean set(Object... keysAndValues) throws JavetException {
if (ArrayUtils.isNotEmpty(keysAndValues)) {
assert keysAndValues.length % 2 == 0 : ERROR_THE_KEY_VALUE_PAIR_MUST_MATCH;
final int length = keysAndValues.length;
final int pairLength = length >> 1;
Object[] keys = new Object[pairLength];
Object[] values = new Object[pairLength];
for (int i = 0; i < pairLength; i++) {
keys[i] = keysAndValues[i * 2];
values[i] = keysAndValues[i * 2 + 1];
}
try (V8VirtualValueList v8VirtualValueKeys = new V8VirtualValueList(checkV8Runtime(), OBJECT_CONVERTER, keys);
V8VirtualValueList v8VirtualValueValues = new V8VirtualValueList(v8Runtime, null, values)) {
V8Value[] v8ValueKeys = v8VirtualValueKeys.get();
V8Value[] v8ValueValues = v8VirtualValueValues.get();
V8Value[] v8Values = new V8Value[length];
for (int i = 0; i < pairLength; i++) {
v8Values[i * 2] = v8ValueKeys[i];
v8Values[i * 2 + 1] = v8ValueValues[i];
}
return v8Runtime.getV8Internal().objectSet(this, v8Values);
}
}
return false;
}
@Override
public boolean setBoolean(Object key, Boolean value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
if (value == null) {
return v8Runtime.getV8Internal().objectSetNull(this, virtualKey.get());
}
return v8Runtime.getV8Internal().objectSetBoolean(this, virtualKey.get(), value);
}
}
@Override
public boolean setDouble(Object key, Double value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
if (value == null) {
return v8Runtime.getV8Internal().objectSetNull(this, virtualKey.get());
}
return v8Runtime.getV8Internal().objectSetDouble(this, virtualKey.get(), value);
}
}
@Override
public boolean setInteger(Object key, Integer value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
if (value == null) {
return v8Runtime.getV8Internal().objectSetNull(this, virtualKey.get());
}
return v8Runtime.getV8Internal().objectSetInteger(this, virtualKey.get(), value);
}
}
@Override
public boolean setLong(Object key, Long value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
if (value == null) {
return v8Runtime.getV8Internal().objectSetNull(this, virtualKey.get());
}
return v8Runtime.getV8Internal().objectSetLong(this, virtualKey.get(), value);
}
}
@Override
public boolean setNull(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectSetNull(this, virtualKey.get());
}
}
@Override
public boolean setPrivateProperty(String propertyName, Object propertyValue) throws JavetException {
Objects.requireNonNull(propertyName);
try (V8VirtualValue virtualValue = new V8VirtualValue(checkV8Runtime(), null, propertyValue)) {
return v8Runtime.getV8Internal().objectSetPrivateProperty(this, propertyName, virtualValue.get());
}
}
@Override
public boolean setProperty(Object key, Object value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key));
V8VirtualValue virtualValue = new V8VirtualValue(v8Runtime, null, value)) {
return v8Runtime.getV8Internal().objectSetProperty(this, virtualKey.get(), virtualValue.get());
}
}
@Override
public boolean setPrototype(V8Value v8Value) throws JavetException {
return set(PROPERTY_PROTOTYPE, Objects.requireNonNull(v8Value));
}
@Override
public boolean setString(Object key, String value) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectSetString(this, virtualKey.get(), value);
}
}
@Override
public boolean setUndefined(Object key) throws JavetException {
try (V8VirtualValue virtualKey = new V8VirtualValue(
checkV8Runtime(), OBJECT_CONVERTER, Objects.requireNonNull(key))) {
return v8Runtime.getV8Internal().objectSetUndefined(this, virtualKey.get());
}
}
@Override
public boolean strictEquals(V8Value v8Value) throws JavetException {
if (!(v8Value instanceof V8ValueObject)) {
return false;
}
if (v8Value.getClass() != this.getClass()) {
return false;
}
V8ValueObject v8ValueObject = (V8ValueObject) v8Value;
if (getHandle() == v8ValueObject.getHandle()) {
return true;
}
return checkV8Runtime().getV8Internal().strictEquals(this, v8ValueObject);
}
@Override
public String toJsonString() {
try {
try (V8ValueBuiltInJson v8ValueBuiltInJson = checkV8Runtime().getGlobalObject().getBuiltInJson()) {
return v8ValueBuiltInJson.stringify(this);
}
} catch (JavetException e) {
return e.getMessage();
}
}
@Override
public String toProtoString() {
try {
return checkV8Runtime().getV8Internal().objectToProtoString(this);
} catch (JavetException e) {
return e.getMessage();
}
}
@Override
public int unbind(Object callbackReceiver) throws JavetException {
Objects.requireNonNull(callbackReceiver);
checkV8Runtime();
int unbindCount = 0;
if (callbackReceiver instanceof IJavetDirectCallable) {
IJavetDirectCallable javetDirectCallable = (IJavetDirectCallable) callbackReceiver;
javetDirectCallable.setV8Runtime(v8Runtime);
for (JavetCallbackContext javetCallbackContext :
Objects.requireNonNull(javetDirectCallable.getCallbackContexts())) {
boolean success;
switch (javetCallbackContext.getCallbackType()) {
case DirectCallSetterAndNoThis:
case DirectCallSetterAndThis:
// Generic getter or setter is ignored and there's no need to unbind setter.
success = false;
break;
case DirectCallGetterAndNoThis:
case DirectCallGetterAndThis:
success = unbindProperty(javetCallbackContext);
break;
default:
success = unbindFunction(javetCallbackContext.getName());
break;
}
if (success) {
++unbindCount;
}
}
} else {
BindingContext bindingContext = getBindingContext(callbackReceiver.getClass());
Map propertyGetterMap = bindingContext.getPropertyGetterMap();
Map functionMap = bindingContext.getFunctionMap();
Method v8BindingEnabler = bindingContext.getV8BindingEnabler();
if (!propertyGetterMap.isEmpty()) {
for (Map.Entry entry : propertyGetterMap.entrySet()) {
String propertyName = entry.getKey();
final MethodDescriptor getterMethodDescriptor = entry.getValue();
try {
if (v8BindingEnabler != null && !(boolean) v8BindingEnabler.invoke(
callbackReceiver, getterMethodDescriptor.getMethod().getName())) {
continue;
}
if (unbindProperty(propertyName, getterMethodDescriptor.getSymbolType())) {
++unbindCount;
}
} catch (Exception e) {
throw new JavetException(
JavetError.CallbackUnregistrationFailure,
SimpleMap.of(
JavetError.PARAMETER_METHOD_NAME, getterMethodDescriptor.getMethod().getName(),
JavetError.PARAMETER_MESSAGE, e.getMessage()),
e);
}
}
}
if (!functionMap.isEmpty()) {
for (Map.Entry entry : functionMap.entrySet()) {
String functionName = entry.getKey();
final MethodDescriptor functionMethodDescriptor = entry.getValue();
try {
if (v8BindingEnabler != null && !(boolean) v8BindingEnabler.invoke(
callbackReceiver, functionMethodDescriptor.getMethod().getName())) {
continue;
}
if (unbindFunction(functionName, functionMethodDescriptor.getSymbolType())) {
++unbindCount;
}
} catch (Exception e) {
throw new JavetException(
JavetError.CallbackUnregistrationFailure,
SimpleMap.of(
JavetError.PARAMETER_METHOD_NAME, functionMethodDescriptor.getMethod().getName(),
JavetError.PARAMETER_MESSAGE, e.getMessage()),
e);
}
}
}
}
return unbindCount;
}
protected boolean unbindFunction(String functionName, V8ValueSymbolType symbolType) throws JavetException {
Objects.requireNonNull(functionName);
switch (Objects.requireNonNull(symbolType)) {
case BuiltIn:
try (V8ValueBuiltInSymbol v8ValueBuiltInSymbol = v8Runtime.getGlobalObject().getBuiltInSymbol();
V8ValueSymbol v8ValueSymbol = v8ValueBuiltInSymbol.getBuiltInSymbol(functionName)) {
if (v8ValueSymbol == null) {
throw new JavetException(
JavetError.ConverterSymbolNotBuiltIn,
SimpleMap.of(JavetError.PARAMETER_SYMBOL, functionName));
}
return delete(v8ValueSymbol);
}
case Custom:
try (V8ValueSymbol v8ValueSymbol = v8Runtime.createV8ValueSymbol(functionName, true)) {
return delete(v8ValueSymbol);
}
default:
return delete(functionName);
}
}
@Override
public boolean unbindProperty(JavetCallbackContext javetCallbackContext) throws JavetException {
return unbindProperty(
Objects.requireNonNull(javetCallbackContext).getName(),
javetCallbackContext.getSymbolType());
}
protected boolean unbindProperty(String propertyName, V8ValueSymbolType symbolType) throws JavetException {
Objects.requireNonNull(propertyName);
switch (Objects.requireNonNull(symbolType)) {
case BuiltIn:
try (V8ValueBuiltInSymbol v8ValueBuiltInSymbol = v8Runtime.getGlobalObject().getBuiltInSymbol();
V8ValueSymbol v8ValueSymbol = v8ValueBuiltInSymbol.getBuiltInSymbol(propertyName)) {
if (v8ValueSymbol == null) {
throw new JavetException(
JavetError.ConverterSymbolNotBuiltIn,
SimpleMap.of(JavetError.PARAMETER_SYMBOL, propertyName));
}
return unbindProperty(v8ValueSymbol);
}
case Custom:
try (V8ValueSymbol v8ValueSymbol = v8Runtime.createV8ValueSymbol(propertyName, true)) {
return unbindProperty(v8ValueSymbol);
}
default:
try (V8ValueString v8ValueString = v8Runtime.createV8ValueString(propertyName)) {
return unbindProperty(v8ValueString);
}
}
}
@Override
public boolean unbindProperty(V8ValueString propertyName) throws JavetException {
return checkV8Runtime().getV8Internal().objectSetAccessor(
this, Objects.requireNonNull(propertyName), null, null);
}
@Override
public boolean unbindProperty(V8ValueSymbol propertyName) throws JavetException {
return checkV8Runtime().getV8Internal().objectSetAccessor(
this, Objects.requireNonNull(propertyName), null, null);
}
}