Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setImmediate is broken in file:// protocols in iOS. #770

Closed
dtinth opened this issue Feb 17, 2020 · 3 comments · Fixed by #771
Closed

setImmediate is broken in file:// protocols in iOS. #770

dtinth opened this issue Feb 17, 2020 · 3 comments · Fixed by #771

Comments

@dtinth
Copy link
Contributor

dtinth commented Feb 17, 2020

Background

We at @taskworld noticed that when our application is running inside Cordova, some Promise would never resolve. Instead, we’d get a weird error message on the console: “Unable to post message to file://. Recipient has origin null.

Upon further investigation, we found that some of our 3rd-party libraries are using an outdated Promise implementation which depends on setImmediate. setImmediate is broken in Cordova, so I decided to file an issue here in core-js.

Investigation

This situation happens in Cordova apps,

  • Web application is run on file:// protocol using Safari’s engine.

  • The defer selection logic selects postMessage to be used (MessageChannel is not used due to IS_IOS clause):

    if (classof(process) == 'process') {
    defer = function (id) {
    process.nextTick(runner(id));
    };
    // Sphere (JS game engine) Dispatch API
    } else if (Dispatch && Dispatch.now) {
    defer = function (id) {
    Dispatch.now(runner(id));
    };
    // Browsers with MessageChannel, includes WebWorkers
    // except iOS - https://github.com/zloirock/core-js/issues/624
    } else if (MessageChannel && !IS_IOS) {
    channel = new MessageChannel();
    port = channel.port2;
    channel.port1.onmessage = listener;
    defer = bind(port.postMessage, port, 1);
    // Browsers with postMessage, skip WebWorkers
    // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
    } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts && !fails(post)) {
    defer = post;
    global.addEventListener('message', listener, false);

  • The postMessage implementation of defer doesn’t work with file: protocol, it errors out with this:

    Unable to post message to file://. Recipient has origin null.
    

Suggested fix

If location.protocol === 'file:', fallback to alternative methods. I made a PR #771 that implements the suggested fix.

Current workaround

require('core-js/stable')

// `setImmediate` is currently broken on Cordova.
// Falling back to `setTimeout` implementation.
//
// See: https://github.com/zloirock/core-js/issues/770
// See also: https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate#Notes
//
window.setImmediate = f => {
  setTimeout(f, 0)
}

I investigated this issue while working on Taskworld, so gotta plug that in. 😄

@diegodalbosco
Copy link

Same problem here. After updating to latest core-js version we cannot deploy our web app to ios (inside a WKWebView that points to local files).

@slowcheetah
Copy link
Contributor

@diegodalbosco try that patch #771
@dtinth thx for solution

@diegodalbosco
Copy link

@slowcheetah We tried the patch and for our use case is working 🎉 Thanks @dtinth!

@slowcheetah slowcheetah mentioned this issue Apr 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants