unotest/source/embindtest/embindtest.js |  129 +++++++++++++++++++-------------
 1 file changed, 80 insertions(+), 49 deletions(-)

New commits:
commit a0f45ceb570d47a9edbadd8bfeeda9b3ee4cf8c6
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Tue Jun 11 17:30:10 2024 +0200
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Wed Jun 12 08:55:53 2024 +0200

    Embind: A nicer unoObject construction function
    
    Change-Id: Ied532cf271644f424fbf9661a0b8d246124ca324
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168689
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>
    Tested-by: Jenkins

diff --git a/unotest/source/embindtest/embindtest.js 
b/unotest/source/embindtest/embindtest.js
index c1670689cf2b..c320fd321687 100644
--- a/unotest/source/embindtest/embindtest.js
+++ b/unotest/source/embindtest/embindtest.js
@@ -641,60 +641,91 @@ Module.addOnPostRun(function() {
         //TODO: verify css.uno.RuntimeException's Message startsWith('test')
         decrementExceptionRefcount(e);
     }
-    const obj = {
-        implRefcount: 0,
-        implTypes: new Module.uno_Sequence_type([
-            Module.uno_Type.Interface('com.sun.star.lang.XTypeProvider'),
-            Module.uno_Type.Interface('com.sun.star.task.XJob'),
-            Module.uno_Type.Interface('com.sun.star.task.XJobExecutor')]),
-        implImplementationId: new Module.uno_Sequence_byte([]),
-        queryInterface(type) {
-            if (type == 'com.sun.star.uno.XInterface') {
-                return new Module.uno_Any(
-                    type, 
css.uno.XInterface.reference(this.implXTypeProvider));
-            } else if (type == 'com.sun.star.lang.XTypeProvider') {
-                return new Module.uno_Any(
-                    type, 
css.lang.XTypeProvider.reference(this.implXTypeProvider));
-            } else if (type == 'com.sun.star.task.XJob') {
-                return new Module.uno_Any(type, 
css.task.XJob.reference(this.implXJob));
-            } else if (type == 'com.sun.star.task.XJobExecutor') {
-                return new Module.uno_Any(
-                    type, 
css.task.XJobExecutor.reference(this.implXJobExecutor));
-            } else {
-                return new Module.uno_Any(Module.uno_Type.Void(), undefined);
+    const unoObject = function(interfaces, obj) {
+        interfaces = ['com.sun.star.lang.XTypeProvider'].concat(interfaces);
+        obj.impl_refcount = 0;
+        obj.impl_types = new Module.uno_Sequence_type(
+            interfaces.length, Module.uno_Sequence.FromSize);
+        for (let i = 0; i !== interfaces.length; ++i) {
+            obj.impl_types.set(i, Module.uno_Type.Interface(interfaces[i]));
+        }
+        obj.impl_implementationId = new Module.uno_Sequence_byte([]);
+        obj.queryInterface = function(type) {
+            for (const i in obj._types) {
+                if (i === type.toString()) {
+                    return new Module.uno_Any(
+                        type,
+                        Module['uno_Type_' + i.replace(/\./g, '$')].reference(
+                            obj._impl[obj._types[i]]));
+                }
             }
-        },
-        acquire() { ++this.implRefcount; },
-        release() {
-            if (--this.implRefcount === 0) {
-                this.implXTypeProvider.delete();
-                this.implXJob.delete();
-                this.implXJobExecutor.delete();
-                this.implTypes.delete();
-                this.implImplementationId.delete();
+            return new Module.uno_Any(Module.uno_Type.Void(), undefined);
+        };
+        obj.acquire = function() { ++obj.impl_refcount; };
+        obj.release = function() {
+            if (--obj.impl_refcount === 0) {
+                for (const i in obj._impl) {
+                    i.delete();
+                }
+                obj.impl_types.delete();
+                obj.impl_implementationId.delete();
             }
-        },
-        getTypes() { return this.implTypes; },
-        getImplementationId() { return this.implImplementationId; },
-        execute(args) {
-            if (args.size() !== 1 || args.get(0).Name !== 'name') {
-                Module.throwUnoException(
-                    
Module.uno_Type.Exception('com.sun.star.lang.IllegalArgumentException'),
-                    {Message: 'bad args', Context: null, ArgumentPosition: 0});
+        };
+        obj.getTypes = function() { return obj.impl_types; };
+        obj.getImplementationId = function() { return 
obj.impl_implementationId; };
+        obj._impl = {};
+        interfaces.forEach((i) => {
+            obj._impl[i] = Module['uno_Type_' + i.replace(/\./g, 
'$')].implement(obj);
+        });
+        obj._types = {};
+        const walk = function(td, impl) {
+            const name = td.getName();
+            if (!Object.hasOwn(obj._types, name)) {
+                if (td.getTypeClass() != css.uno.TypeClass.INTERFACE) {
+                    throw new Error('not a UNO interface type: ' + name);
+                }
+                obj._types[name] = impl;
+                const bases = 
css.reflection.XInterfaceTypeDescription2.query(td).getBaseTypes();
+                for (let i = 0; i !== bases.size(); ++i) {
+                    walk(bases.get(i), impl)
+                }
+                bases.delete();
             }
-            console.log('Hello ' + args.get(0).Value.get());
-            return new Module.uno_Any(Module.uno_Type.Void(), undefined);
-        },
-        trigger(event) { console.log('Ola ' + event); }
+        };
+        const tdmAny = Module.getUnoComponentContext().getValueByName(
+            '/singletons/com.sun.star.reflection.theTypeDescriptionManager');
+        const tdm = css.container.XHierarchicalNameAccess.query(tdmAny.get());
+        interfaces.forEach((i) => {
+            const td = tdm.getByHierarchicalName(i);
+            walk(css.reflection.XTypeDescription.query(td.get()), i);
+            td.delete();
+        })
+        tdmAny.delete();
+        obj._types['com.sun.star.uno.XInterface'] = 
'com.sun.star.lang.XTypeProvider';
+        obj.acquire();
+        return obj;
     };
-    obj.implXTypeProvider = css.lang.XTypeProvider.implement(obj);
-    obj.implXJob = css.task.XJob.implement(obj);
-    obj.implXJobExecutor = css.task.XJobExecutor.implement(obj);
-    obj.acquire();
-    test.passJob(css.task.XJob.reference(obj.implXJob));
-    
test.passJobExecutor(css.task.XJobExecutor.reference(obj.implXJobExecutor));
-    test.passInterface(css.uno.XInterface.reference(obj.implXTypeProvider));
+    const obj = unoObject(
+        ['com.sun.star.task.XJob', 'com.sun.star.task.XJobExecutor'],
+        {
+            execute(args) {
+                if (args.size() !== 1 || args.get(0).Name !== 'name') {
+                    Module.throwUnoException(
+                        
Module.uno_Type.Exception('com.sun.star.lang.IllegalArgumentException'),
+                        {Message: 'bad args', Context: null, ArgumentPosition: 
0});
+                }
+                console.log('Hello ' + args.get(0).Value.get());
+                return new Module.uno_Any(Module.uno_Type.Void(), undefined);
+            },
+            trigger(event) { console.log('Ola ' + event); }
+        });
+    test.passJob(css.task.XJob.reference(obj._impl['com.sun.star.task.XJob']));
+    test.passJobExecutor(
+        
css.task.XJobExecutor.reference(obj._impl['com.sun.star.task.XJobExecutor']));
+    
test.passInterface(css.uno.XInterface.reference(obj._impl['com.sun.star.lang.XTypeProvider']));
     obj.release();
+    test.StringAttribute = 'hä';
+    console.assert(test.StringAttribute === 'hä');
 
     const args = new Module.uno_Sequence_any(
         [new 
Module.uno_Any(Module.uno_Type.Interface('com.sun.star.uno.XInterface'), 
test)]);

Reply via email to