oracle / cordova-plugin-wkwebview-file-xhr

Cordova Plugin for WebView File XHR
Universal Permissive License v1.0
138 stars 120 forks source link

TypeError: req.dispatchEvent is not a function #32

Closed mgatto closed 5 years ago

mgatto commented 5 years ago

Hello,

I get the above error when loading any asset file with a relative path from JS such as templates/config.js. But, initial loading worked perfectly when assets are referenced in the index.html file, when Cordova apparently auto-sets the URLs as so: file:///var/containers/Bundle/Application/67FAC6E7-FDC1-488D-8458-ABCF6872CC02/myApp.app/www/js/printer.js.

The error is

[Error] Unhandled Promise Rejection: TypeError: req.dispatchEvent is not a function. (In 'req.dispatchEvent(event)', 'req.dispatchEvent' is undefined)
    (anonymous function) (xhr-polyfill.js:1000)
    (anonymous function) (util.js:5)
    _presend (xhr-polyfill.js:181)
    send (xhr-polyfill.js:237)
    (anonymous function) (xhr-polyfill.js:1232)
    promiseReactionJob

My project uses jQuery to handle create AJAX calls. All assets are located within www/

Debugging shows this data with a breakpoint just above line 1000 in xhr-polyfill.js:

event: undefined
readyState: undefined
req: 1

Thanks.

gvanmat commented 5 years ago

If you turn on full logging, you should see the complete requests in the JS console logs and in xcode too - NativeXHRLogging preference.

https://github.com/oracle/cordova-plugin-wkwebview-file-xhr/blob/master/README.md#configuration

mgatto commented 5 years ago

Right, I had <preference name="NativeXHRLogging" value="full" /> set in my config.xml, but all I get in the Safari console is

xhr-polyfill.js - native file XHR Request:
"templates/config.js"

and in XCode, even less:

2019-04-25 16:40:38.815711-0700 myApp[1689:845739] "templates/config.js"

If it helps, in the JS debugger, I see:

this: Object
    async: true
    delegate: null
    dispatchProgressEvent: function()
    dispatchReadyStateChangeEvent: function()
    dispatchUploadProgressEvent: function()
    listeners: {}
    method: "GET"
    password: undefined
    readyState: undefined
...
gvanmat commented 5 years ago

It kind of sounds like the send method on XMLHttpRequest is being invoked out of context. As in if the send method was not getting invoked off the instance of the object but a reference to the function was called without binding context to an instance of XMLHttpRequest.

Can you set a breakpoint in the "window.XMLHttpRequest.prototype.send" and look at the call stack to determine the jquery code invoking the send?

mgatto commented 5 years ago

Hi Gary,

I've created a screen shot with the call stack and the state of some local vars from the Safari debugger.

Screen Shot 2019-04-26 at 1 44 18 PM
mgatto commented 5 years ago

Oh, I think my app's code is borking this. There's a util.js in our codebase, but not in the plugin which is getting called, and it all falls down because of our code here:

Function.prototype.bind = function (bind) {
    var self = this;
    return function () {
        var args = Array.prototype.slice.call(arguments);
        return self.apply(bind || null, args);
    };
};
gvanmat commented 5 years ago

Ah ok. That is likely the issue. You don't need to polyfill bind as ES5 JS standard is supported by wkwebview.

mgatto commented 5 years ago

Right, its legacy code which I inherited as a maintainer. I'll start to strip it out, so I'll close this report. Thanks so much; You helped me zero in on the cause!