All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.caoccao.javet.interop.converters.JavetProxyConverter Maven / Gradle / Ivy

Go to download

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

There is a newer version: 4.0.0
Show newest version
/*
 * 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.interop.converters;

import com.caoccao.javet.annotations.CheckReturnValue;
import com.caoccao.javet.annotations.V8Convert;
import com.caoccao.javet.enums.V8ProxyMode;
import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interop.V8Runtime;
import com.caoccao.javet.interop.V8Scope;
import com.caoccao.javet.interop.callback.JavetCallbackContext;
import com.caoccao.javet.interop.proxy.*;
import com.caoccao.javet.utils.JavetResourceUtils;
import com.caoccao.javet.values.V8Value;
import com.caoccao.javet.values.primitive.V8ValueLong;
import com.caoccao.javet.values.reference.IV8ValueObject;
import com.caoccao.javet.values.reference.V8ValueObject;
import com.caoccao.javet.values.reference.V8ValueProxy;
import com.caoccao.javet.values.reference.builtin.V8ValueBuiltInObject;

import java.util.List;

/**
 * The type Javet proxy converter converts most of Java objects to
 * JS objects via JS proxy bi-directionally.
 * 

* Java Primitive types, Array, List, Set and Map are converted to the * corresponding types in JS. Set and Map conversion can be disabled * via config. * * @since 0.9.6 */ @SuppressWarnings("unchecked") public class JavetProxyConverter extends JavetObjectConverter { /** * The constant DUMMY_FUNCTION_STRING contains a JS code snippet * which creates an empty anonymous function hidden in a closure. * The purpose is to avoid polluting the context because a * non-anonymous function can possibly conflict with a variable * with the same name in the same context. * * @since 0.9.8 */ protected static final String DUMMY_FUNCTION_STRING = "(() => {\n" + " const DummyFunction = function () { };\n" + " return DummyFunction;\n" + "})();"; /** * Instantiates a new Javet proxy converter. * * @since 0.9.6 */ public JavetProxyConverter() { super(); } /** * To proxied V8 value. * * @param the type parameter * @param v8Runtime the V8 runtime * @param object the object * @return the proxied V8 value * @throws JavetException the javet exception */ @CheckReturnValue protected T toProxiedV8Value(V8Runtime v8Runtime, Object object) throws JavetException { V8Value v8Value; if (object instanceof IJavetNonProxy) { v8Value = v8Runtime.createV8ValueUndefined(); } else { V8ProxyMode proxyMode = V8ProxyMode.Object; Class objectClass = object.getClass(); if (object instanceof Class) { if (V8ProxyMode.isClassMode((Class) object)) { proxyMode = V8ProxyMode.Class; } } else if (objectClass.isAnnotationPresent(V8Convert.class)) { V8Convert v8Convert = objectClass.getAnnotation(V8Convert.class); if (v8Convert.proxyMode() == V8ProxyMode.Function) { proxyMode = V8ProxyMode.Function; } } try (V8Scope v8Scope = v8Runtime.getV8Scope()) { V8ValueProxy v8ValueProxy; V8Value v8ValueTarget = null; try { switch (proxyMode) { case Class: v8ValueTarget = JavetProxyPrototypeStore.createOrGetPrototype( v8Runtime, proxyMode, (Class) object); break; case Function: v8ValueTarget = JavetProxyPrototypeStore.createOrGetPrototype( v8Runtime, proxyMode, objectClass); break; default: if (object instanceof IJavetDirectProxyHandler) { IJavetDirectProxyHandler javetDirectProxyHandler = (IJavetDirectProxyHandler) object; javetDirectProxyHandler.setV8Runtime(v8Runtime); v8ValueTarget = javetDirectProxyHandler.createTargetObject(); } else { V8ProxyMode v8ProxyMode = proxyMode; v8ValueTarget = getConfig().getProxyPlugins().stream() .filter(p -> p.isProxyable(objectClass)) .findFirst() .map(p -> p.getTargetObjectConstructor(objectClass)) .map(f -> { try { return f.invoke(v8Runtime, object); } catch (Throwable ignored) { } return null; }) .orElseGet(() -> { try (V8Value v8ValuePrototype = JavetProxyPrototypeStore.createOrGetPrototype( v8Runtime, v8ProxyMode, objectClass); V8ValueBuiltInObject v8ValueBuiltInObject = v8Runtime.getGlobalObject().getBuiltInObject(); V8ValueObject v8ValueObject = v8Runtime.createV8ValueObject()) { return v8ValueBuiltInObject.setPrototypeOf(v8ValueObject, v8ValuePrototype); } catch (Throwable ignored) { } return null; }); } break; } v8ValueProxy = v8Scope.createV8ValueProxy(v8ValueTarget); } finally { JavetResourceUtils.safeClose(v8ValueTarget); } try (IV8ValueObject iV8ValueObjectHandler = v8ValueProxy.getHandler()) { IJavetProxyHandler javetProxyHandler; switch (proxyMode) { case Class: javetProxyHandler = new JavetReflectionProxyClassHandler<>(v8Runtime, (Class) object); break; case Function: if (object instanceof IJavetDirectProxyHandler) { javetProxyHandler = new JavetDirectProxyFunctionHandler<>( v8Runtime, (IJavetDirectProxyHandler) object); } else { javetProxyHandler = new JavetReflectionProxyFunctionHandler<>(v8Runtime, object); } break; default: if (object instanceof IJavetDirectProxyHandler) { javetProxyHandler = new JavetDirectProxyObjectHandler<>( v8Runtime, (IJavetDirectProxyHandler) object); } else { javetProxyHandler = new JavetReflectionProxyObjectHandler<>(v8Runtime, object); } break; } List javetCallbackContexts = iV8ValueObjectHandler.bind(javetProxyHandler); try (V8ValueLong v8ValueLongHandle = v8Runtime.createV8ValueLong( javetCallbackContexts.get(0).getHandle())) { iV8ValueObjectHandler.setPrivateProperty(PRIVATE_PROPERTY_PROXY_TARGET, v8ValueLongHandle); } } v8Value = v8ValueProxy; v8Scope.setEscapable(); } } return (T) v8Value; } @Override @CheckReturnValue protected T toV8Value( V8Runtime v8Runtime, Object object, final int depth) throws JavetException { if (object instanceof V8Value) { return (T) object; } boolean proxyable = false; if (object != null) { if (object instanceof IJavetDirectProxyHandler) { proxyable = true; } else if (!(object instanceof IJavetNonProxy)) { final Class objectClass = object.getClass(); proxyable = getConfig().getProxyPlugins().stream().anyMatch(p -> p.isProxyable(objectClass)); } } if (!proxyable) { final V8Value v8Value = super.toV8Value(v8Runtime, object, depth); if (v8Value != null && !(v8Value.isUndefined())) { return (T) v8Value; } } return toProxiedV8Value(v8Runtime, object); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy