Skip to content

[WebView] onMessage failing when there are JS warnings and errors on the page #10865

Closed
@raiderrobert

Description

@raiderrobert

Description

I'm receiving this error (same as screenshot below):

Setting onMessage on a WebView overrides existing values of window.postMessage, 
but a previous value was defined.

screen shot 2016-11-10 at 3 33 31 pm

That specific error message is found in the code base here: https://github.com/facebook/react-native/blob/master/React/Views/RCTWebView.m#L286

Implementation

I followed the example at this link for onMessage at this link: http://facebook.github.io/react-native/releases/0.37/docs/webview.html#examples

I made a callable respondToOnMessage and injected some JavaScript.

class MessagingTest extends React.Component {

    respondToOnMessage = e =>{
        console.log(e);
    };

    render() {
        const jsCode = `window.postMessage('test');`;

        return (
        <WebView
        injectedJavaScript={jsCode}
        source={uri: 'https://www.foo.com/'}}
        onMessage={this.respondToOnMessage}
        />
        )
    }
}

Reproduction

I load the app with this example and I have it pointed to a website (rather not say which one. Sorry.) And the website is emitting 2 errors into the Chrome console when I go there.

(index):994 A Parser-blocking, cross-origin script, http://example.com/thing.js, is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity.

widgets.js:8 Uncaught TypeError: Cannot set property '[object Array]' of undefined(…)

Other websites like google.com and github.com are just fine. If you want to replicate it, change the uri to yahoo.com

Additional Information

  • React Native version: 0.37
  • Platform: iOS 10.1, iPhone 6 emulator
  • Operating System: Mac OSX Sierra 10.12.1

Activity

raiderrobert

raiderrobert commented on Nov 10, 2016

@raiderrobert
Author

I should also add that I attempted to replicate the error on Android 7.0 and API 24 using a Nexus_5x emulator, and I got NO error. So this seems to be a platform specific error.

sreucherand

sreucherand commented on Nov 11, 2016

@sreucherand

I'm getting the same error. Seems like this exception is thrown when window.postMessage has been overwritten. But since webViewDidFinishLoad is called multiple times, it tries to overwrite window.postMessage over and over. Not sure though. Can we have you expertise @jacobp100?

jacobp100

jacobp100 commented on Nov 11, 2016

@jacobp100
Contributor

It’s because the page you’re visiting is overriding postMessage, which may be due to a shim. Showing an error was chosen over invoking the shim’s value of postMessage when you call the value of postMessage that we set.

I thought I’d made it easier to workaround this problem, but it looks like that won’t work. The best you can do at the moment, which is an awful hack, is,

injectedJavaScript="window.postMessage = String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');"

Or just fork the project and remove the code you pointed to. Whatever’s easiest for you!

Ping @satya164 for input on how to resolve.

sreucherand

sreucherand commented on Nov 11, 2016

@sreucherand

Well, when I try String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage') on the page I visit, it returns true, so I am guessing postMessage has not been overridden.

jacobp100

jacobp100 commented on Nov 11, 2016

@jacobp100
Contributor

Oh I see. The JS is injected after postMessage is overwritten. Your best bet is to fork it then, and I’ll see what I can do about getting this fixed! Sorry. :(

persyl

persyl commented on Nov 20, 2016

@persyl

I have same error, without injecting any javascript to WebView - just setting WebView-properties:

source={require('../lib/html/somefile.html')}
onMessage={() => console.log('Hello World')}

and in my ../lib/html/somefile.html' I have javascript code doing both window.postMessage() and document.addEventListener("message",.......

Everything worked fine when I had the HTML in a variable "someHtml", like:
source={{html: someHtml}}

So difference seem to be when changing source to HTML-file instead of HTML-string.

Still for me I had other reasons, not related to this, why I really need to read HTML from file instead of string so it would be great to get this issue fixed.

cbcye

cbcye commented on Nov 20, 2016

@cbcye

+1, still has this problem

jacobp100

jacobp100 commented on Nov 20, 2016

@jacobp100
Contributor

There is an ongoing discussion in #10941 for the best way to go forward with this.

It won't be in the next release or probably the release after. If you need this fixed now, fork the project and use the fix in the PR.

lealife

lealife commented on Dec 19, 2016

@lealife

+1, I'm getting the same error. When there is a iframe on web, it occurs the same error

varhp

varhp commented on Dec 21, 2016

@varhp

+1,encounter this problem

jacobp100

jacobp100 commented on Dec 21, 2016

@jacobp100
Contributor

Again, there is a pr for this. We're aware this problem is affecting a lot of people.

edencakir

edencakir commented on Dec 26, 2016

@edencakir

+1 getting the same error.

kyle-ilantzis

kyle-ilantzis commented on Dec 31, 2016

@kyle-ilantzis

injectedJavascript should instead be the following

(function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'); 
  };

  window.postMessage = patchedPostMessage;
})();

And then it works! 😄

And if any one is interested, in my code instead of writing a giant string I did the following

const patchPostMessageFunction = function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

...

<WebView injectedJavaScript={patchPostMessageJsCode} />
mschipperheyn

mschipperheyn commented on Jan 21, 2017

@mschipperheyn

@kyle-ilantzis tried this with RN 0.38.1, but still get the Red Screen. What version of RN are you on?

115 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @0x6e6562@jigfox@jeveloper@hramos@abeauvois

      Issue actions

        [WebView] onMessage failing when there are JS warnings and errors on the page · Issue #10865 · facebook/react-native