Environment
Problem
New window is opened from parent window. Webchimera module is loaded but it crashes because its window object points to parent window. That is because NW.js caches its modules.
PARENT
<div id="chimera_container"></div>
...
var gui; // global variable for parent object
var wjs; // global variable for parent object
....
gui = require('nw.gui');
wjs = wjs = require('wcjs-player');
....
video_emit = gui.Window.open('video_emit.html',{
"window" : {
"focus": true,
"toolbar": true,
"frame": true,
"width" : 640,
"height" : 640
},
"dependencies": {
"require-new": "^1.1.0",
"wcjs-player": "^0.5.6"
},
});
video_emit window
<div id="vid"></div>
....
var wjs; // global variable for new window object
wjs = require('wcjs-player');
video_container = new wjs("#vid"); <---- CRASHES **** !!!
In the node_modules\wcjs-player\index.js line 82 I added
console.log(window.document);
PARENT CONSOLE OUTPUT
#document
...
<div id="chimera_container"></div>
video_emit CONSOLE OUTPUT
#document
...
<div id="chimera_container"></div>
Solutions tried
Manually clearing cache
Calling function clearRequiredModules before requiring 'wcjs-player' module on video_emit window.
var clearRequiredModules = function(){
// clear wcjs-player from require cache to force new load
var clearModules = [
"wcjs-player",
"jquery" // https://github.com/jaruba/wcjs-player/issues/38
];
for (var i in clearModules) {
for (var module in global.require.cache) {
if ( global.require.cache.hasOwnProperty(module)
&& module.indexOf(clearModules[i]) > -1
)
delete global.require.cache[module];
}
}
};
Not working. Same problem as if I hadn't cleared at all. Still points to parent window object.
Using require-new module
There's no science to this code, I load module and use it in video_emit window.
var req_new = require('require-new');
wjs = req_new('wcjs-player');
Still crashes.
I know that adding ** new-instance: true** to the gui.Window.open
of the parent would fix this, but I need parent and new window to communicate via the global variable usable only if they are on the same render.
------------------------ Solution -----------------------------------------
Clearing cache on its own didn't work, in order for it to be valid the following had to be done from the parent window.
video_emit = gui.Window.open('video_emit.html',{
...
});
video_emit .on('document-start', function() {
video_emit .reload(3);
});
And in the child window:
clearRequiredModules(); //Same code as protrayed above
wjs = require('wcjs-player');
video_container = new wjs("#vid");
PROBLEM
BEWARE, doing this renders the global variable (the one used to share information between windows, useless. So it's the same as doing this in parent window (and not clearing cache in child window):
video_emit = gui.Window.open('video_emit.html',{
"window" : {
"focus": true,
"toolbar": true,
"frame": true,
"width" : 640,
"height" : 640
},
"new-instance" : true // <---- That right there
});
A possible solution to this problem is to use localStorage instead, to communicate between windows.
wcjs-player
is heavily reliant on being able to access window.document
. NW.js
v0.12.3 has a bug that leaks the parent's window
object to the child window.
I've seen this create numerous issues including pushing all errors and logs to the main window, and it always breaks all modules that are dependent on window
.
The fix for this is to do a node.js level reload of the child window after creating it.
Example Usage:
var new_win = require('nw.gui').Window.open('index.html');
new_win.on('document-start', function() {
new_win.reload(3);
});
Notes:
It should also be mentioned that this is a NW.js
specific issue, Electron
does not have this issue with new windows.
As this is a high level page reload, the global
object will also be cleared, an alternative solution to passing information to this new window is using localStorage
(that is persistent), or for more complex needs websockets.