JSO: fix wrapping undefined value

This commit is contained in:
Alexey Andreev 2023-12-07 10:02:22 +01:00
parent 9093ad2f8a
commit a9af6e4f33
2 changed files with 26 additions and 3 deletions

View File

@ -35,6 +35,7 @@ public final class JSWrapper {
? JSMap.create() : null;
private static final JSMap<JSNumber, JSWeakRef<JSObject>> numberWrappers = JSWeakRef.isSupported()
? JSMap.create() : null;
private static JSWeakRef<JSObject> undefinedWrapper;
private static final JSFinalizationRegistry stringFinalizationRegistry;
private static final JSFinalizationRegistry numberFinalizationRegistry;
private static int hashCodeGen;
@ -59,12 +60,13 @@ public final class JSWrapper {
return null;
}
var js = directJavaToJs(o);
if (isJSImplementation(o)) {
var type = JSObjects.typeOf(js);
var isObject = type.equals("object") || type.equals("function");
if (isObject && isJSImplementation(o)) {
return o;
}
if (wrappers != null) {
var type = JSObjects.typeOf(js);
if (type.equals("object") || type.equals("function")) {
if (isObject) {
var existingRef = get(wrappers, js);
var existing = !JSObjects.isUndefined(existingRef) ? deref(existingRef) : JSObjects.undefined();
if (JSObjects.isUndefined(existing)) {
@ -100,6 +102,17 @@ public final class JSWrapper {
} else {
return jsToWrapper(existing);
}
} else if (type.equals("undefined")) {
var existingRef = undefinedWrapper;
var existing = existingRef != null ? deref(existingRef) : JSObjects.undefined();
if (JSObjects.isUndefined(existing)) {
var wrapper = new JSWrapper(js);
var wrapperAsJs = wrapperToJs(wrapper);
undefinedWrapper = createWeakRef(wrapperAsJs);
return wrapper;
} else {
return jsToWrapper(existing);
}
}
}
return new JSWrapper(js);

View File

@ -311,6 +311,16 @@ public class JSWrapperTest {
}));
}
@Test
public void wrapUndefined() {
field1 = JSObjects.undefined();
assertEquals("undefined", field1.toString());
assertEquals(JSObjects.undefined(), field1);
assertSame(JSObjects.undefined(), field1);
assertTrue(field1 instanceof JSObject);
assertTrue(JSObjects.isUndefined(field1));
}
private void callSetProperty(Object instance, Object o) {
setProperty(instance, "foo", o);
}