diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java index 3ff556744..bf81f91df 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java @@ -35,6 +35,7 @@ public final class JSWrapper { ? JSMap.create() : null; private static final JSMap> numberWrappers = JSWeakRef.isSupported() ? JSMap.create() : null; + private static JSWeakRef 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); diff --git a/tests/src/test/java/org/teavm/jso/test/JSWrapperTest.java b/tests/src/test/java/org/teavm/jso/test/JSWrapperTest.java index 1d3bd268f..5067ee228 100644 --- a/tests/src/test/java/org/teavm/jso/test/JSWrapperTest.java +++ b/tests/src/test/java/org/teavm/jso/test/JSWrapperTest.java @@ -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); }