目录

JavaScript

本指南描述了如何在加载的网页上访问 JavaScript、执行 JavaScript 代码、注入 Java 对象以从 JavaScript 调用 Java 等操作。

执行 JavaScript 

JxBrowser 允许在加载的网页上访问和执行 JavaScript 代码。

要访问 JavaScript,请确保网页已完全加载,并启用 JavaScript。

要执行 JavaScript 代码,请使用 Frame.executeJavaScript(String) 方法。此方法会阻塞当前线程的执行,并等待给定的代码执行完毕。该方法返回一个表示执行结果的 java.lang.Object。如果执行结果为 null 或 undefined,则该方法返回 null。

以下示例执行返回 document 标题的 JavaScript 代码:

Java
Kotlin

String title = frame.executeJavaScript("document.title");

val title = frame.executeJavaScript<String>("document.title")

您可以执行任何 JavaScript 代码:

Java
Kotlin

double number = frame.executeJavaScript("123");
boolean bool = frame.executeJavaScript("true");
String string = frame.executeJavaScript("'你好'");
JsFunction alert = frame.executeJavaScript("window.alert");
JsObject window = frame.executeJavaScript("window");
Element body = frame.executeJavaScript("document.body");
JsPromise promise = frame.executeJavaScript("Promise.resolve('Success')");
JsArray array = frame.executeJavaScript("['苹果', '香蕉']");
JsArrayBuffer arrayBuffer = frame.executeJavaScript("new ArrayBuffer(8)");
JsSet set = frame.executeJavaScript("new Set([1, 2, 3, 4])");
JsMap map = frame.executeJavaScript("new Map([['李白', '32'], ['李清照', '26']])");

val number = frame.executeJavaScript<Double>("123")
val bool = frame.executeJavaScript<Boolean>("true")
val string = frame.executeJavaScript<String>("'你好'")
val alert = frame.executeJavaScript<JsFunction>("window.alert")
val window = frame.executeJavaScript<JsObject>("window")
val body = frame.executeJavaScript<Element>("document.body")
val promise = frame.executeJavaScript<JsPromise>("Promise.resolve('Success')")
val array = frame.executeJavaScript<JsArray>("['苹果', '香蕉']")
val arrayBuffer = frame.executeJavaScript<JsArrayBuffer>("new ArrayBuffer(8)")
val set = frame.executeJavaScript<JsSet>("new Set([1, 2, 3, 4])")
val map = frame.executeJavaScript<JsMap>("new Map([['李白', '32'], ['李清照', '26']])")

如果您不想阻塞当前线程的执行,您可以使用 Frame.executeJavaScript(String javaScript, Consumer<?> callback) 方法。此方法异步执行给定的 JavaScript 代码,并通过提供的 callback 返回执行结果:

Java
Kotlin

frame.executeJavaScript("document.body", (Consumer<Element>) body -> {
    var html = body.innerHtml();
});

frame.executeJavaScript("document.body", Consumer<Element> { body ->
    val html = body.innerHtml()
})

类型转换 

JavaScript 和 Java 使用不同的原始类型。JxBrowser 实现了从 JavaScript 到 Java 类型的自动转换,反之亦然。

将 JavaScript 转换为 Java 

以下规则用于将 JavaScript 转换为 Java 类型:

  • JavaScript numbers 转换为 java.lang.Double
  • JavaScript string 转换为 java.lang.String
  • JavaScript boolean 转换为 java.lang.Boolean
  • JavaScript null 或者 undefined 转换为 null
  • JavaScript Promise 转换为 JsPromise
  • JavaScript BigInt 转换为 java.math.BigInteger
  • JavaScript 对象被包装为 JsObject
  • JavaScript 函数被包装为 JsFunction
  • JavaScript DOM 节点对象被包装为 JsObject 和 EventTarget
  • JavaScript ArrayBuffer 被包装为 JsArrayBuffer
  • JavaScript Array 被包装为 JsArray
  • JavaScript Set 被包装为 JsSet
  • JavaScript Map 被包装为 JsMap
  • JavaScript Symbol 被包装为 JsSymbol

在上面的例子中我们知道 document.title 是一个字符串,所以我们将返回值设置为 java.lang.String。

将 Java 转换为 JavaScript 

以下规则用于将 Java 转换为 JavaScript 类型:

  • java.lang.Double 转换为 JavaScript Number
  • java.lang.String 转换为 JavaScript string
  • java.lang.Boolean 转换为 JavaScript boolean
  • Java null 转换为 JavaScript null
  • JsObject 转换为适当的 JavaScript object
  • JsPromise 转换为 JavaScript Promise
  • EventTarget 转换为适当的 JavaScript DOM 节点对象
  • java.math.BigInteger 转换为 BigInt
  • java.lang.Object 被包装为一个 JavaScript 代理对象
  • java.util.List<?> 转换为 JavaScript Array 或代理对象
  • JsArray 转换为 JavaScript Array
  • java.util.Set<?> 转换为 JavaScript Set 或代理对象
  • JsSet 转换为 JavaScript Set
  • java.util.Map<?,?> 转换为 JavaScript Map 或代理对象
  • JsMap 转换为 JavaScript Map
  • byte[] 转换为 JavaScript ArrayBuffer
  • JsArrayBuffer 转换为 JavaScript ArrayBuffer
  • JsSymbol 转换为 JavaScript Symbol

如果将非原始 Java 对象传递给 JavaScript,它将被转换为代理对象。对此对象的方法和属性调用将委托给 Java 对象。出于安全原因,JavaScript 只能访问那些使用 @JsAccessible 注释或 JsAccessibleTypes 类显式标记为可访问的注入 Java 对象的方法和字段。

如果 Java 集合没有使用 @JsAccessible 或通过 JsAccessibleTypes 类来使 JavaScript 可以访问,它们将被转换为 JavaScript 集合。转换后的集合内容是 Java 集合的深拷贝。JavaScript 中对转换后集合的修改不会影响 Java 中的集合。

如果 Java 集合通过 @JsAccessible 注解或通过 JsAccessibleTypes 类被设置为 JavaScript 可访问,它们将被包装成 JavaScript 代理对象。此类代理对象可用于修改 Java 中的集合。

DOM 包装器 

根据自动类型转换的规则,JavaScript DOM 对象被包装为 JsObject 和 EventTarget。这使您能够通过 JxBrowser DOM API 操作 JavaScript DOM 对象。

在以下示例中,我们返回表示 JavaScript DOM 对象的 document。在这种情况下,返回值可以设置为 JsObject 或 Document:

Java
Kotlin

Document document = frame.executeJavaScript("document");

val document = frame.executeJavaScript<Document>("document")
Java
Kotlin

JsObject document = frame.executeJavaScript("document");

val document = frame.executeJavaScript<JsObject>("document")

使用 JsObject 

要从 Java 代码中操作 JavaScript 对象,请使用 JsObject 类。该类允许操作对象的属性并调用其函数。

属性 

要获取 JavaScript 对象的属性名称,包括原型对象的属性,请使用 propertyNames() 方法:

Java
Kotlin

var propertyNames = jsObject.propertyNames();

val propertyNames = jsObject.propertyNames()

要检查 JavaScript 对象是否具有指定属性,请使用 hasProperty(String) 方法:

Java
Kotlin

var has = jsObject.hasProperty("<property-name>");

val has = jsObject.hasProperty("<property-name>")

要通过名称获取 JavaScript 对象属性的值,请使用 property(String)。例如:

Java
Kotlin

JsObject document = frame.executeJavaScript("document");
document.property("title").ifPresent(title -> {});

val document = frame.executeJavaScript<JsObject>("document")!!
document.property<String>("title").ifPresent { title -> }

返回值表示 java.lang.Object 它可以被设置为所需的类型。请参阅类型转换。

您可以使用以下方法移除属性:

Java
Kotlin

var success = jsObject.removeProperty("<property-name>");

val success = jsObject.removeProperty("<property-name>")

函数 

要调用具有所需名称和参数的函数,请使用 call(String methodName, Object... args) 方法。以下示例演示了如何调用 document.getElementById() 函数:

Java
Kotlin

JsObject element = document.call("getElementById", "elementId");

val element: JsObject = document.call("getElementById", "elementId")

这相当于 JavaScript 中的以下代码:

var element = document.getElementById("demo");

如果在函数执行期间发生错误,该方法将抛出 JsException。

关闭 

具有 JsObject 对应项的 V8 对象不受 V8 垃圾回收机制的影响。默认情况下,我们会将这些对象保留在内存中,直到页面卸载。

为了优化内存使用,您可以基于每个对象启用垃圾回收:

Java
Kotlin

jsObject.close();

jsObject.close()

关闭 JsObject 会将相应的 Blink 对象标记为可回收对象,但它不会立即释放该对象。在调用 close() 方法后,尝试使用 JsObject 将导致 ObjectClosedException。

JsFunctionCallback 

另一种从 JavaScript 调用 Java 的方法是使用 JsFunctionCallback。

JavaScript-Java 桥接允许您将 JsFunctionCallback 与 JavaScript 属性相关联,该属性将被视为可以在 JavaScript 代码中调用的函数。

例如,您可以使用以下代码注册一个与 JsFunctionCallback 实例相关联的 JavaScript 函数:

Java
Kotlin

JsObject window = frame.executeJavaScript("window");
if (window != null) {
    window.putProperty("sayHello", (JsFunctionCallback) args ->
        "你好, " + args[0]
    );
}

val window = frame.executeJavaScript<JsObject>("window")
window?.putProperty("sayHello", JsFunctionCallback { args -> "你好, ${args[0]}" })

现在,在 JavaScript 中,您可以通过以下方式调用此函数:

window.sayHello('李白');

JsFunction 

从 7.7 版本开始,您可以直接从 Java 代码中使用 JavaScript 函数,并将对函数的引用从 JavaScript 传递给 Java。例如:

Java
Kotlin

JsObject window = frame.executeJavaScript("window");
if (window != null) {
    JsFunction alert = frame.executeJavaScript("window.alert");
    if (alert != null) {
        alert.invoke(window, "你好,世界!");
    }
}

val window = frame.executeJavaScript<JsObject>("window")
if (window != null) {
    val alert = frame.executeJavaScript<JsFunction>("window.alert")
    alert?.invoke<Any>(window, "你好,世界!")
}

JsPromise 

从 7.17 版本开始,您可以直接在 Java 代码中使用 JavaScript Promises。例如:

Java
Kotlin

JsPromise promise = frame.executeJavaScript("""
        new Promise(function(resolve, reject) {
                        setTimeout(function() {
                            resolve("你好 Java!");
                        }, 2000);"
                    })"""
);
promise.then(results -> {
    System.out.println(results[0]);
    return promise;
}).then(results -> {
    System.out.println(results[0]);
    return promise;
}).catchError(errors -> {
    System.out.println(errors[0]);
    return promise;
});

val promise = frame.executeJavaScript<JsPromise>("""
    new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("你好 Java!");
        }, 2000);
    })
""")!!
promise.then { results ->
    println(results[0])
    promise
}.then { results ->
    println(results[0])
    promise
}.catchError { errors ->
    println(errors[0])
    promise
}

JsSymbol 

您可以使用 JsSymbol 接口在 Java 中直接操作 JavaScript Symbol 对象。例如:

Java
Kotlin

JsSymbol symbol = frame.executeJavaScript("Symbol('bacf2f')");
symbol.description().ifPresent(description -> {
    System.out.println(description);
});

val symbol = frame.executeJavaScript<JsSymbol>("Symbol('bacf2f')")!!
symbol.description().ifPresent { description ->
    println(description)
}

JavaScript 集合 

您可以在 Java 代码中直接操作 JavaScript 的数组(Array)、集合(Set) 和 映射(Map)。当这些 JavaScript 数据结构的实例被传递到 Java 中时,JxBrowser 会自动将它们转换为特殊的包装类型:

Java
Kotlin

JsMap map = frame.executeJavaScript("new Map([['key', 'value']]);");
JsSet set = frame.executeJavaScript("new Set(['item'])");
JsArray array = frame.executeJavaScript("['foo', 'bar']");

val map: JsMap? = frame.executeJavaScript<JsMap>("new Map([['key', 'value']]);")
val set: JsSet? = frame.executeJavaScript<JsSet>("new Set(['item'])")
val array: JsArray? = frame.executeJavaScript<JsArray>("['foo', 'bar']")

JsMap、JsSet 和 JsArray 类直接与底层 V8 数据结构交互,除非您明确请求,否则不会复制数据。这些类的方法接受原始类型、任意 Java 对象以及 JsObject 实例,这些实例将根据 Java 到 JavaScript 的转换规则 进行转换。

Map 

要向 map(映射)中添加元素,请使用 JsMap.add(Object key, Object value) 方法:

Java
Kotlin

map.set("key", "value");

map["key"] = "value"

要从 map 中获取元素,请使用 JsMap.get(Object) 方法:

Java
Kotlin

var value = map.get("key");

val value: Any = map["key"]

要检查 map 中是否存在某个键,请使用 JsMap.has(Object) 方法:

Java
Kotlin

var hasKey = map.has("key");

val hasKey = map.has("key")

要从 map 中删除元素,请使用 JsMap.delete(Object) 方法:

Java
Kotlin

map.delete("key");

map.delete("key")

要获取 map 的大小,请使用 JsMap.size() 方法:

Java
Kotlin

long size = map.size();

val size = map.size()

要清空 map 中的所有元素,请使用 JsMap.clear() 方法:

Java
Kotlin

map.clear();

map.clear()

要将 JavaScript 的 map 转换为 java.uti.Map,请使用 JsMap.toMap() 方法,该方法会复制数据:

Java
Kotlin

Map<Object, Object> javaMap = map.toMap();
Map<String, JsObject> typedJavaMap = map.toMap(String.class, JsObject.class);

val javaMap = map.toMap()
val typedJavaMap = map.toMap(String::class.java, JsObject::class.java)

Set 

要向 set(集合)中添加元素,请使用 JsSet.add(Object) 方法:

Java
Kotlin

set.add("item");

set.add("item")

要从 set 中删除元素,请使用 JsSet.delete(Object) 方法:

Java
Kotlin

set.delete("item");

set.delete("item")

要清空 set,请使用 JsSet.clear() 方法:

Java
Kotlin

set.clear();

set.clear()

要检查 set 中是否存在某个元素,请使用 JsSet.has(Object) 方法:

Java
Kotlin

var hasItem = set.has("item");

val hasItem = set.has("item")

要读取 set 的大小,请使用 JsSet.size() 方法:

Java
Kotlin

var size = set.size();

val size = set.size()

要将 JavaScript 的 set 转换为 java.util.Set,请使用 JsSet.toSet() 方法,该方法会复制数据:

Java
Kotlin

Set<Object> javaSet = set.toSet();
Set<String> typedJavaSet = set.toSet(String.class);

val javaSet: Set<Any> = set.toSet()
val typedJavaSet: Set<String> = set.toSet(String::class.java)

Array 

要从 array(数组)中读取元素,请使用 JsArray.get(long) 方法:

Java
Kotlin

var item = array.get(42);

val item: Any? = array[42]

要按索引设置 array 元素,请使用 JsArray.set(long) 方法:

Java
Kotlin

array.set(42, "Item");

array[42] = "Item"

要读取 array 的长度,请使用 JsArray.length() 方法:

Java
Kotlin

var length = array.length();

val length = array.length()

要将 JavaScript 的 array 转换为 java.util.List,请使用 JsArray.toList() 方法,该方法会复制数据:

Java
Kotlin

List<Object> javaList = array.toList();
List<JsObject> typedJavaList = array.toList(JsObject.class);

val javaList = array.toList()
val typedJavaList = array.toList(JsObject::class.java)

从 JavaScript 调用 Java 

当您将 java.lang.Object 作为属性值传递,或者在调用 JavaScript 函数时作为参数传递时,Java 对象将自动包装成 JavaScript 对象。

它允许将 Java 对象注入 JavaScript,并从 JavaScript 调用其公共方法和字段。

出于安全原因,只有使用 @JsAccessible 注解的公共非静态方法和字段,或者在标记了 @JsAccessible 注解的类中声明的方法和字段,才能从 JavaScript 中访问。带注释的 protected、private 或 package-private 方法和字段,或者在类中使用此类修饰符声明的方法和字段,在 JavaScript 中是不可访问的。

要将 Java 对象注入 JavaScript,请定义 Java 对象类,并使用 @JsAccessible 标记应可从 JavaScript 中访问的公共方法:

Java
Kotlin

public final class JavaObject {
    @JsAccessible
    public String sayHelloTo(String firstName) {
        return "你好 " + firstName + "!";
    }
}

class JavaObject {
    @JsAccessible
    fun sayHelloTo(firstName: String) = "你好 $firstName!"
}

在加载的网页上执行 JavaScript 之前,将一个 Java 对象的实例注入到 JavaScript 中:

Java
Kotlin

browser.set(InjectJsCallback.class, params -> {
    JsObject window = params.frame().executeJavaScript("window");
    window.putProperty("java", new JavaObject());
    return InjectJsCallback.Response.proceed();
});

browser.register(InjectJsCallback { params ->
    val window = params.frame().executeJavaScript<JsObject>("window")
    window?.putProperty("java", JavaObject())
    InjectJsCallback.Response.proceed()
})

现在您可以从 JavaScript 引用该对象并调用其方法:

window.java.sayHelloTo("李白");

注释规则 

@JsAccessible 注解允许将注入的 Java 对象的方法和字段暴露给 JavaScript。

您只能使公共类型、方法和字段可访问。支持的完整情况列表如下:

  • 顶级类或接口
  • 嵌套的静态类或接口
  • 类或接口的非静态方法
  • 类的非静态字段

该注释不能应用于非公共类型、方法和字段。非公共类型的公共方法和字段被认为是非公共的。当您注释一个类型时,其所有公共方法和字段都会变得对 JavaScript 可访问。当您注释一个未注释类型的方法或字段时,只有注释的成员会对 JavaScript 可访问。

当可访问的方法在子类中被重写时,它仍然保持可访问。这意味着您可以使一个接口可访问,并将其任何实现传递给 JavaScript:接口中声明的所有方法都将从 JavaScript 可访问。在实现类中声明的其他方法和字段将保持不可访问,除非您显式地用此注释标记它们或整个类型。

另一种使类型可从 JavaScript 访问的方法是使用 JsAccessibleTypes。当您想要一个核心 Java 类型之一(例如 java.util.List)可访问,或第三方库中的类型可访问而无法使用此注释访问时,这特别有用。

例子:

公共顶级类的注释方法和字段是可访问的:

Java
Kotlin

public final class TopClassDemo {
    @JsAccessible
    public Object accessibleField;
    @JsAccessible
    public void accessibleMethod() {}
}

class TopClassDemo {
    @JsAccessible
    var accessibleField: Any? = null
    @JsAccessible
    fun accessibleMethod() {}
}

公共静态嵌套类的注释方法和字段是可访问的:

Java
Kotlin

public final class TopClassWithNestedDemo {
    public static class NestedClass {
        @JsAccessible
        public Object accessibleField;
        @JsAccessible
        public void accessibleMethod() {}
    }
}

class TopClassWithNestedDemo {
    class NestedClass {
        @JsAccessible
        var accessibleField: Any? = null
        @JsAccessible
        fun accessibleMethod() {}
    }
}

带注释类的未注释方法和字段是可访问的:

Java
Kotlin

@JsAccessible
public final class ClassWithUnannotatedMembersDemo {
    public Object accessibleField;
    public void accessibleMethod() {}
}

@JsAccessible
class ClassWithUnannotatedMembersDemo {
    var accessibleField: Any? = null
    fun accessibleMethod() {}
}

带注释的基类的方法和字段可以从继承者访问:

Java
Kotlin

public final class AccessFromInheritorsDemo {
    @JsAccessible
    public static class BaseNestedClass {
        public Object accessibleFieldFromInheritor;
        public void accessibleMethodFromInheritor() {}
    }
    public static class NestedClass extends BaseNestedClass {
        public Object inaccessibleField;
        public void inaccessibleMethod() {}
    }
}

class AccessFromInheritorsDemo {
    @JsAccessible
    open class BaseNestedClass {
        var accessibleFieldFromInheritor: Any? = null
        fun accessibleMethodFromInheritor() {}
    }
    class NestedClass : BaseNestedClass() {
        var inaccessibleField: Any? = null
        fun inaccessibleMethod() {}
    }
}

如果继承的方法和字段或它们所声明的类没有被注释,则不可访问:

Java
Kotlin

public final class UnannotatedClassAccessDemo {
    public static class BaseNestedClass {
        public Object inaccessibleField;
        public void inaccessibleMethod() {}
    }
    @JsAccessible
    public static class NestedClass extends BaseNestedClass {
        public Object accessibleField;
        public void accessibleMethod() {}
    }
}

class UnannotatedClassAccessDemo {
    open class BaseNestedClass {
        var inaccessibleField: Any? = null
        fun inaccessibleMethod() {}
    }
    @JsAccessible
    class NestedClass : BaseNestedClass() {
        var accessibleField: Any? = null
        fun accessibleMethod() {}
    }
}

覆盖类的方法是可访问的:

Java
Kotlin

public final class OverriddenMethodsAccessDemo {
    public static class BaseNestedClass {
        @JsAccessible
        public void method() {}
    }
    public static class NestedClass extends BaseNestedClass {
        @Override
        public void method() {} // 可访问。
    }
}

class OverriddenMethodsAccessDemo {
    open class BaseNestedClass {
        @JsAccessible
        open fun method() {
        }
    }
    class NestedClass : BaseNestedClass() {
        override fun method() {} // 可访问。
    }
}

已实现的接口方法是可访问的:

Java
Kotlin

public final class ImplInterfaceMethodsAccessDemo {
    public interface NestedInterface {
        @JsAccessible
        void method();
    }
    public static class AccessibleImplementor implements NestedInterface {
        @Override
        public void method() { } // 可访问。
    }
}

class ImplInterfaceMethodsAccessDemo {
    interface NestedInterface {
        @JsAccessible
        fun method()
    }
    class AccessibleImplementor : NestedInterface {
        override fun method() {} // 可访问。
    }
}

如果可访问的 Java 方法的签名包含原始数字参数,则将检查从 JavaScript 传递的数字是否有可能转换为 Java 参数类型。如果可以在无损情况下执行转换,并且没有找到其他合适的重载方法,则调用该方法。

如果存在多个可以接受传递参数的方法,JavaScript 将会抛出异常,指示请求的方法调用存在歧义,无法执行。

如果找不到与请求的名称对应的方法或字段,JavaScript 将会抛出异常,指示请求的成员不存在。

如果 JavaScript 请求的方法和字段具有相同名称,则 JavaScript 将会抛出异常,指示请求的成员不明确,无法访问。

自动类型转换 

当从 JavaScript 调用注入的 Java 对象的公共方法时,JavaScript-Java 桥接提供自动类型转换功能。

该库会在可能的情况下,自动将给定的 JavaScript Number 转换为所需的 Java 类型。如果我们检测到给定的数字不能无损地转换为 Java 的某个类型,例如 byte,那么该库会抛出一个异常并通知 JavaScript 没有合适的 Java 方法。如果给定的值可以在无损情况下进行转换,那么库会进行转换并调用相应的 Java 方法。

例如,如果您将以下 Java 对象注入到 JavaScript 中:

Java
Kotlin

public final class JavaObjectWithTypeConversion {
    @JsAccessible
    public int method(int intValue) {
        return intValue;
    }
}

class JavaObjectWithTypeConversion {
    @JsAccessible
    fun method(intValue: Int) = intValue
}

然后您就可以从 JavaScript 调用它,并传递一个可以无损转换为 Integer 的 JavaScript Number 值:

window.javaObject.method(123);

但是,如果您传递的 Double 值无法在无损情况下转换为 Integer,则会出现错误:

window.javaObject.method(3.14); // <- error

从库中调用 

注入的 Java 对象是一种特殊的对象。它们的行为与常规 JavaScript 对象不同,并且不打算直接传递给 JavaScript 库。

在 JavaScript 库中使用它们之前,我们建议使用 Proxy 进行封装。在这个例子中,我们创建了一个代理对象,它实现了对 JS 可访问成员的读取访问:

const proxy = new Proxy({__java: myJavaObject}, {
    get(target, prop, receiver) {
        for (let javaMemberName in target.__java) {
            if (prop === javaMemberName) {
                return target.__java[prop]
            }
        }
        return Reflect.get(...arguments);
    },
    ...
});

控制台消息 

JxBrowser 允许接收通过 console.log() JavaScript 函数发送到控制台的所有输出消息。您可以监听以下级别的消息:

  • DEBUG
  • LOG
  • WARNING
  • ERROR

要在控制台收到消息时获得通知,请使用 ConsoleMessageReceived 事件。例如:

Java
Kotlin

browser.on(ConsoleMessageReceived.class, event -> {
    var consoleMessage = event.consoleMessage();
    var level = consoleMessage.level();
    var message = consoleMessage.message();
});

browser.subscribe<ConsoleMessageReceived> { event ->
    val consoleMessage = event.consoleMessage()
    val level = consoleMessage.level()
    val message = consoleMessage.message()
}

JSON 

JxBrowser 提供了一个辅助类,用于 JavaScript 对象与 JSON 格式之间的相互转换:

Java
Kotlin

Json json = frame.json();

val json = frame.json()

Json 类允许您在特定框架的 JavaScript 上下文中基于 JSON 字符串创建对象。

Java
Kotlin

JsObject parsedObject = json.parse("{'name': 'John'}");

val parsedObject = frame.json().parse<JsObject>("{'name': 'John'}")

同样,您可以将 JavaScript 对象转换为 JSON 字符串:

Java
Kotlin

JsObject myObject = frame.executeJavaScript("window.myobject");
String myObjectAsJson = frame.json().stringify(myObject);

val myObject = frame.executeJavaScript<JsObject>("window.myobject")
val myObjectAsJson = frame.json().stringify(myObject!!)

Json 的实现依赖于 V8 的 JSON 函数,因此与 JavaScript 内置的 JSON 命名空间具有相同的限制。