GraalVM - 在没有上下文的情况下使用多语言值
GraalVM - Using Polyglot Value without a context
我正在 Graal 上编写一个应用程序,它将能够执行不同语言的小脚本。
我正在尝试为我正在使用的 class 编写一些单元测试 convert/process Context.eval() 调用(类型:值)的结果 Java 对象。我从文档中知道一个 Value 实例总是绑定到一个上下文,所以当我尝试写这样的东西时:
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
我收到以下错误:
java.lang.IllegalStateException: No current context is available. Make sure the Java method is invoked by a Graal guest language or a context is entered using Context.enter().
我想从概念上讲,拥有一个没有关联的访客代码位的 "Value" 实例是没有意义的,所以我的问题是:
我该如何着手测试我的 GuestLanguageResultProcessor class?我是否必须 "bloat" 通过创建上下文来进行单元测试?
专家的附带问题:我还使用这个 class (GuestLanguageResultProcessor) 从多语言值实例中提取 Java 值,以便我可以关闭上下文。换句话说,在我看来,在能够执行 Context.close() 之前,我需要调用 [value instance].asString() 或 .asWhatever() 才能得到结果并能够关闭context 而不会像 docs.
中所说的那样得到 IllegalStateException
我做的对吗?有没有更好的方法来处理获取结果和安全关闭上下文?
谢谢!
How can I go about testing my GuestLanguageResultProcessor class? Do I have to "bloat" my unit test with the creation of a context?
我担心有点腹胀是必要的。我建议使用以下代码来使您的测试工作。这也可以在测试基地 class 中完成,以避免重复。
Context context;
@Before
public void setup() {
context = Context.create();
context.enter();
}
@After
public void setup() {
context.leave();
context.close();
}
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
Am I doing it right? Is there a better way to handle getting the result and closing the context safely?
值实例可能会绑定到来宾语言对象,例如 Java脚本对象,一旦上下文关闭,这些对象就会失效。并非总是可以将来宾语言对象转换为永久 Java 表示。例如,多语言值可能指的是 JavaScript 对象的整个图形。
如果可能,我建议只要需要值就保持上下文打开,因为它不需要任何转换。
如果这不可能,并且您只处理基元和数组,您可以尝试使用以下方法。您也可以尝试通过访问其成员将对象复制到 Java 土地。
Object copyToJavaLand(Value value) {
if (value.isBoolean()) {
return value.asBoolean();
} else if (value.isString()) {
return value.asString();
} else if (value.isNumber()) {
return value.as(Number.class);
} else if (value.isHostObject()) {
return value.asHostObject();
} else if (value.isProxyObject()) {
return value.asProxyObject();
} else if (value.hasArrayElements()) {
Object[] array = new Object[(int) value.getArraySize()];
for (int i = 0; i < array.length; i++) {
array[i] = copyToJavaLand(value.getArrayElement(i));
}
return array;
}
throw new IllegalArgumentException("Cannot copy value " + value + ".");
}
请注意,此方法并不总是安全的。例如,如果数组引用自身,此方法将因堆栈溢出错误而崩溃。
我正在 Graal 上编写一个应用程序,它将能够执行不同语言的小脚本。
我正在尝试为我正在使用的 class 编写一些单元测试 convert/process Context.eval() 调用(类型:值)的结果 Java 对象。我从文档中知道一个 Value 实例总是绑定到一个上下文,所以当我尝试写这样的东西时:
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
我收到以下错误:
java.lang.IllegalStateException: No current context is available. Make sure the Java method is invoked by a Graal guest language or a context is entered using Context.enter().
我想从概念上讲,拥有一个没有关联的访客代码位的 "Value" 实例是没有意义的,所以我的问题是:
我该如何着手测试我的 GuestLanguageResultProcessor class?我是否必须 "bloat" 通过创建上下文来进行单元测试?
专家的附带问题:我还使用这个 class (GuestLanguageResultProcessor) 从多语言值实例中提取 Java 值,以便我可以关闭上下文。换句话说,在我看来,在能够执行 Context.close() 之前,我需要调用 [value instance].asString() 或 .asWhatever() 才能得到结果并能够关闭context 而不会像 docs.
中所说的那样得到 IllegalStateException我做的对吗?有没有更好的方法来处理获取结果和安全关闭上下文?
谢谢!
How can I go about testing my GuestLanguageResultProcessor class? Do I have to "bloat" my unit test with the creation of a context?
我担心有点腹胀是必要的。我建议使用以下代码来使您的测试工作。这也可以在测试基地 class 中完成,以避免重复。
Context context;
@Before
public void setup() {
context = Context.create();
context.enter();
}
@After
public void setup() {
context.leave();
context.close();
}
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
Am I doing it right? Is there a better way to handle getting the result and closing the context safely?
值实例可能会绑定到来宾语言对象,例如 Java脚本对象,一旦上下文关闭,这些对象就会失效。并非总是可以将来宾语言对象转换为永久 Java 表示。例如,多语言值可能指的是 JavaScript 对象的整个图形。
如果可能,我建议只要需要值就保持上下文打开,因为它不需要任何转换。
如果这不可能,并且您只处理基元和数组,您可以尝试使用以下方法。您也可以尝试通过访问其成员将对象复制到 Java 土地。
Object copyToJavaLand(Value value) {
if (value.isBoolean()) {
return value.asBoolean();
} else if (value.isString()) {
return value.asString();
} else if (value.isNumber()) {
return value.as(Number.class);
} else if (value.isHostObject()) {
return value.asHostObject();
} else if (value.isProxyObject()) {
return value.asProxyObject();
} else if (value.hasArrayElements()) {
Object[] array = new Object[(int) value.getArraySize()];
for (int i = 0; i < array.length; i++) {
array[i] = copyToJavaLand(value.getArrayElement(i));
}
return array;
}
throw new IllegalArgumentException("Cannot copy value " + value + ".");
}
请注意,此方法并不总是安全的。例如,如果数组引用自身,此方法将因堆栈溢出错误而崩溃。