Search code examples
javascriptvb6chromium-embedded

What should I check? Uncaught (in promise) TypeError: Cannot read property 'MyFunctionName' of undefined URL


The problem only occurs in the compiled application, so I guess it's a browser specific specific problem, but I'm not sure:

I have added the following script to a webpage:

async function exportChatAsXMLHelper(params){
    let displayname     = params[0];
    let includeMedia    = params[1];
    let debug           = params[2];
    
    await exportChatAsXML(displayname, includeMedia, debug);
}

async function exportChatAsXML(displayname, includeMedia, debug)
{

    let chat = (await WPP.chat.list()).find(m => m.contact && m.contact.name && m.contact.name.includes(displayname));
    await WPP.chat.openChatBottom(chat.id);
    let msgs = await WPP.chat.getMessages(chat.id, {count : -1});

    const log = (obj) => debug && console.log(obj);
    
    log('Total messages: ' + msgs.length);

    let count=msgs.length;

    for (var i = 0; i < count; i++) {
        log('Message number: ' + i);

        let message = msgs[i];
        let xml='';
        xml+= '<message>';
        xml+= '<sender>'+ message.from.user +'</sender>';
        xml+= '<receiver>'+ message.to.user +'</receiver>';

        xml+= '<type>'+ (message.type || '') +'</type>';

        if(message.type == 'chat')
        {
            xml+= '<body>'+ message.body +'</body>';
        }

        if(message.type != 'chat' && includeMedia) 
        {
            xml+= '<media>';
            xml+= '<caption>'+ (message.caption || '') +'</caption>';
            xml+= '<filename>'+ (message.filename || '') +'</filename>';

            log('Downloading media');

            try
            {
                let mediabody = await mediatoBase64(message.id);
                xml+= '<MediaDownloadStatus>success</MediaDownloadStatus>';
                xml+= '<base64>'+ mediabody +'</base64>';
            }
            catch(e)
            {
                xml+= '<base64></base64>';
                xml+= '<MediaDownloadStatus>fail</MediaDownloadStatus>';
            }
            xml+= '</media>';
        }

        xml+= '</message>';

        alert('before'); //this is still shown

        //where is JSCallbackReceiver defined? it is from vb6
       window.JSCallbackReceiver.OnWhatsAppXMLReceived(i, count, xml);
       
       alert('after'); //this is not shown

       xml='';
    }
}


//-----
async function mediatoBase64(msgid) {
    let blob = await WPP.chat.downloadMedia(msgid);
    return new Promise((resolve, _) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result);
        reader.readAsDataURL(blob);
    });
}

It works fine on my developer's machine, but throws an error on a client's machine:

Uncaught (in promise) TypeError: Cannot read property 'OnWhatsAppXMLReceived' of undefined https://web.whatsapp.com/ 80

I have added some alerts now to see where exactely it goes wrong. The alert "before" is shown, the alert "after" is not shown, so the error definitively occurs in

   window.JSCallbackReceiver.OnWhatsAppXMLReceived(i, count, xml);
   alert('after');

What could I check to see what exactely goes wrong / what is different on the client's machine?

The callback object is defined in VB6 like this:

Private m_JSCallback As clsJSCallbackReceiver

Set m_JSCallback = New clsJSCallbackReceiver
Me.webkit1.AddObject "JSCallbackReceiver", m_JSCallback

Does the error message mean that the browser does not find the object that I added via AddObject?

I am using mobileFx webkit browser which is based on Chromium, but I guess that is not important.

This is what the class clsJSCallbackReceiver looks like in VB6:

Option Explicit
    
Public Sub OnWhatsAppXMLReceived(ByVal uIndex As Long, ByVal uCount As Long, ByVal uXml As String)

     Debug.Print("I was called!")
    
 End Sub

 Public Sub SaySomething(ByVal u As String)
     MsgBox(u)
 End Sub

Thank you!

Edit:

I only happens when compiled. When I run it in the VB6 IDE, it works fine.

After the error occurs, I can still call

m_JSCallback.SaySomething("Hello!")

, and it will work.

So the object is still alive. It is just not connected to the browser, I guess.


Solution

  • I found this document, which says this about an example they've given:

    "Next, since the Instancing property of the class is PublicNotCreatable, the project must provide a way for a client to instantiate the object. Add a new function in a standard module. Where clsEmployee is the name of the class of interest. Also, this should not be a private module."

    And your code seems to contradict that.