offapi/org/libreoffice/embindtest/XTest.idl |    2 ++
 static/README.wasm.md                       |   14 +++++++-------
 static/source/embindmaker/embindmaker.cxx   |   13 +++++--------
 unotest/source/embindtest/embindtest.cxx    |   11 +++++++++++
 unotest/source/embindtest/embindtest.js     |   11 +++++++++++
 5 files changed, 36 insertions(+), 15 deletions(-)

New commits:
commit 1c81f63e91d39187748ea070d064e996481dbd3d
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Thu Apr 18 16:05:48 2024 +0200
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Fri Apr 19 21:20:59 2024 +0200

    Embind: Consistently represent empty interface references as JS null
    
    The existing code had two issues:  For one, e.g. calling a function that
    returned a null interface reference mapped that to JS null, while querying 
an
    object for a non-supported interface via `new css.uno.X...(y)` mapped that 
to
    an "empty" JS object instead.  (So checking for a non-null reference needed 
to
    be done as either `x !=== null` or as `x.is()`, depending on context.)  And 
for
    another, while calling $is() on a non-"empty" object worked fine, it failed 
on
    such an "empty" object (as the Embind internals of that object lacked the $$
    property).
    
    So change the querying mechanism from the `new css.uno.X...(y)` constructor 
to a
    `css.uno.X....query(y)` function call syntax, which now returns JS null when
    querying for a non-supported interface.  (And drop the broken $is method.)
    
    Change-Id: I8fa488ab2892423f2a461d9b72db47e1d4df3b8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166255
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>

diff --git a/offapi/org/libreoffice/embindtest/XTest.idl 
b/offapi/org/libreoffice/embindtest/XTest.idl
index 8817e94669fc..3dc1773c120a 100644
--- a/offapi/org/libreoffice/embindtest/XTest.idl
+++ b/offapi/org/libreoffice/embindtest/XTest.idl
@@ -112,6 +112,8 @@ interface XTest {
     boolean isSequenceEnum([in] sequence<Enum> value);
     sequence<Struct> getSequenceStruct();
     boolean isSequenceStruct([in] sequence<Struct> value);
+    XTest getNull();
+    boolean isNull([in] XTest value);
     void throwRuntimeException();
     void passJob([in] com::sun::star::task::XJob object);
     void passJobExecutor([in] com::sun::star::task::XJobExecutor object);
diff --git a/static/README.wasm.md b/static/README.wasm.md
index 19da4518030c..5397e2124d16 100644
--- a/static/README.wasm.md
+++ b/static/README.wasm.md
@@ -228,11 +228,11 @@ Some usage examples through javascript of the current 
implementation:
 let uno = init_unoembind_uno(Module);
 let css = uno.com.sun.star;
 xModel = Module.getCurrentModelFromViewSh();
-xTextDocument = new css.text.XTextDocument(xModel);
+xTextDocument = css.text.XTextDocument.query(xModel);
 xText = xTextDocument.getText();
-xSimpleText = new css.text.XSimpleText(xText);
+xSimpleText = css.text.XSimpleText.query(xText);
 xTextCursor = xSimpleText.createTextCursor();
-xTextRange = new css.text.XTextRange(xTextCursor);
+xTextRange = css.text.XTextRange.query(xTextCursor);
 xTextRange.setString("string here!");
 xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); 
xTextCursor.delete(); xTextRange.delete();
 ```
@@ -242,13 +242,13 @@ xModel.delete(); xTextDocument.delete(); xText.delete(); 
xSimpleText.delete(); x
 let uno = init_unoembind_uno(Module);
 let css = uno.com.sun.star;
 xModel = Module.getCurrentModelFromViewSh();
-xEnumAccess = new css.container.XEnumerationAccess(xText);
+xEnumAccess = css.container.XEnumerationAccess.query(xText);
 xParaEnumeration = xEnumAccess.createEnumeration();
 
 while (xParaEnumeration.hasMoreElements()) {
-    xParagraph = new css.text.XTextRange(xParaEnumeration.nextElement().get());
-    if (xParagraph.$is()) {
-        xParaProps = new css.beans.XPropertySet(xParagraph);
+    xParagraph = 
css.text.XTextRange.query(xParaEnumeration.nextElement().get());
+    if (xParagraph !== null) {
+        xParaProps = css.beans.XPropertySet.query(xParagraph);
         let color = new Module.uno_Any(
             Module.uno_Type.Long(), Math.floor(Math.random() * 0xFFFFFF));
         xParaProps.setPropertyValue("CharColor", color);
diff --git a/static/source/embindmaker/embindmaker.cxx 
b/static/source/embindmaker/embindmaker.cxx
index 252d7b25451c..abce7e574f67 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -1082,18 +1082,15 @@ SAL_IMPLEMENT_MAIN()
                       "        .smart_ptr<::com::sun::star::uno::Reference<"
                    << cppName(ifc) << ">>(\"uno_Reference_" << jsName(ifc)
                    << "\")
"
+                      "        .class_function(\"query\", "
+                      
"+[](::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> "
+                      "const & the_object) { return 
::com::sun::star::uno::Reference<"
+                   << cppName(ifc)
+                   << ">(the_object, ::com::sun::star::uno::UNO_QUERY); })
"
                       "        .class_function(\"reference\", +[]("
                    << cppName(ifc)
                    << " * the_interface) { return 
::com::sun::star::uno::Reference(the_interface); "
                       "}, ::emscripten::allow_raw_pointers())
"
-                      "        "
-                      
".constructor(+[](::com::sun::star::uno::Reference<::com::sun::star::uno::"
-                      "XInterface> const & the_object) { return 
::com::sun::star::uno::Reference<"
-                   << cppName(ifc)
-                   << ">(the_object, ::com::sun::star::uno::UNO_QUERY); })
"
-                      "        .function(\"$is\", 
+[](::com::sun::star::uno::Reference<"
-                   << cppName(ifc)
-                   << "> const & the_self) { return the_self.is(); })
"
                       "        .function(\"$equals\", 
+[](::com::sun::star::uno::Reference<"
                    << cppName(ifc)
                    << "> const & the_self, "
diff --git a/unotest/source/embindtest/embindtest.cxx 
b/unotest/source/embindtest/embindtest.cxx
index c5127a2fe695..9c10335ed704 100644
--- a/unotest/source/embindtest/embindtest.cxx
+++ b/unotest/source/embindtest/embindtest.cxx
@@ -501,6 +501,17 @@ class Test : public 
cppu::WeakImplHelper<org::libreoffice::embindtest::XTest>
                   };
     }
 
+    css::uno::Reference<org::libreoffice::embindtest::XTest> SAL_CALL 
getNull() override
+    {
+        return {};
+    }
+
+    sal_Bool SAL_CALL
+    isNull(css::uno::Reference<org::libreoffice::embindtest::XTest> const& 
value) override
+    {
+        return !value;
+    }
+
     void SAL_CALL throwRuntimeException() override
     {
         throw css::uno::RuntimeException(u"test"_ustr);
diff --git a/unotest/source/embindtest/embindtest.js 
b/unotest/source/embindtest/embindtest.js
index 7d69f9908cdf..f3bd0df2740e 100644
--- a/unotest/source/embindtest/embindtest.js
+++ b/unotest/source/embindtest/embindtest.js
@@ -517,6 +517,17 @@ Module.addOnPostRun(function() {
         console.assert(test.isSequenceStruct(v));
         v.delete();
     }
+    {
+        let v = test.getNull();
+        console.log(v);
+        console.assert(v === null);
+        console.assert(test.isNull(v));
+    }
+    {
+        let v = css.task.XJob.query(test);
+        console.log(v);
+        console.assert(v === null);
+    }
     console.assert(uno.org.libreoffice.embindtest.Constants.Boolean === true);
     
console.assert(test.isBoolean(uno.org.libreoffice.embindtest.Constants.Boolean));
     console.assert(uno.org.libreoffice.embindtest.Constants.Byte === -12);

Reply via email to