nwjs / nw.js

Call all Node.js modules directly from DOM/WebWorker and enable a new way of writing applications with all Web technologies.
https://nwjs.io
MIT License
40.31k stars 3.88k forks source link

0.23.7: When executed in a NW.js event handler setTimeout does not invoke its callback function #6069

Open semmel opened 7 years ago

semmel commented 7 years ago

Must be a regression, since it has worked fine until after NW.js 0.22.3 The behaviour occurs for NW.js 0.23.7 in event handlers like nw.Window.on('close', handler).

I am running NW.js in Separate Context Mode without --mixed-context option.

An event handler like nw.Window.on('close', handler) has the Browser Context version of setTimeout in the global JS context. The observed behaviour is that it's worker function is never executed.

As a workaround one can employ setTimeout from the Node.js Context: global.setTimeout.

Here is the demo (Simply run in the Developer Console of the SDK build of NW.js 0.23.7)

nw.Window.open("https://www.example.com", { id: "Homepage", position:"center", width: 400, height: 600, resizable: true}, function(nwWindow){ 
 nwWindow.on('close', function(){
   // works on 0.23.7
    global.setTimeout(console.log.bind(console, "You can read this."), 500); 
    // works just on 0.22.3
    setTimeout(console.log.bind(console, "This is never executed"), 500);
  });

  nwWindow.close();
});

My workaround is to replace the Browser Context version of setTimeout entirely with the Node.js Context version:

setTimeout = global.setTimeout.bind(global);
clearTimeout = global.clearTimeout.bind(global);

To my surprise this seems to work.

Maybe setInterval is also affected?

Christywl commented 7 years ago

I can reproduce this issue on Linux/Windows on nwjs-sdk-v0.24.0.

rogerwang commented 7 years ago

After digging into it I found it should be expected: the 'setTimeout' function is bound to the global window object of the first window (which is under the security origin of chrome-extension://xyz), while the callback is executed in the context of the second window (security origin: www.example.com), which doesn't have the access to the first window and its function.

rogerwang commented 7 years ago

btw, using 'nwWindow.window.setTimeout' works as expected.

semmel commented 7 years ago

I think the callback should also have the context of the first window (chrome-extension://xyz).