Here is the index.js
file:
// -------------------------------------------------------------
/// Testing and playing
// -------------------------------------------------------------
var sw = require('./setWindow');
// -------------------------------------------------------------
const {
setTimeout,
setImmediate,
} = require("sdk/timers");
var TABS = require("sdk/tabs");
var browserWindows = require("sdk/windows").browserWindows;
// -------------------------------------------------------------
// Marck start time
var tmr = Date.now();
// -------------------------------------------------------------
/// Listeners:
browserWindows.on('open', function (win) {
log('~win', getWinId(win), 'open', win.tabs.length, win.tabs[0].id);
});
// on open tabs might be uninitialized and it is dangerous to alter it in any way
TABS.on('open', function (tab, event) {
log('~tab', tab.id, 'open', tab.readyState, tab.url, event?true:event);
});
// This one is not documented, but interesting
TABS.on('create', function (tab, ...args) {
log('~tab', tab.id, 'create', tab.readyState, tab.url, ...args);
});
TABS.on('ready', function (tab) {
log('~tab', tab.id, 'ready', tab.readyState, tab.url);
});
TABS.on('load', function (tab) {
log('~tab', tab.id, 'load', tab.readyState, tab.url);
});
TABS.on('move', function (tab, ...args) {
log('~tab', tab.id, 'move', tab.readyState, tab.url, ...args);
});
/// Some URLs
var urls = [
'https://duzun.me/?window1_tab0_open_before_window',
'https://www.google.com/?window1_tab1_detatched_to_window3',
'https://nodejs.org/en/?window1_tab3_next_to_detatched_tab',
'https://discourse.mozilla-community.org/t/tear-off-tab-with-sdk/7085/19/',
'http://npmjs.org/?window2_tab1_moved_to_window1',
];
/// Experiments
var w0 = browserWindows[0];
w0.tabs[0].url = urls[3];
var w1 = browserWindows.open({
url: urls[0],
onOpen: function (w) {
// Can't open any tab on this window until t0.readyState != 'uninitialized', so use what SDK offers - onReady,
// even though it depends on document.readyState == 'interactive' inside tab, which could take a lot of time to happen :-(
var t0 = w.tabs[0];
t0.once('ready', function (t0) {
w.tabs.open({
url: urls[1],
index: 1,
onOpen: function (t1) {
log('~t1', t1.id,'detaching', getWinId(t1.window));
t1.detach();
// This one would try to access .url multiple times, thus throws an error
wait4url(t1, log);
},
});
w.tabs.open({
url: urls[2],
index: 3,
});
});
var t4 = w0.tabs[0];
t4.once('ready', function (t4) {
w0.tabs.open({
url: urls[4],
onReady: (tab) => {
log('~move tab', tab.id, tab.url, 'from', getWinId(w0), 'to', getWinId(w1));
tab.setWindow(w1);
},
});
});
}
});
/// Helpers:
function passed() {
return Date.now() - tmr;
}
function log(...args) {
console.log(passed(), '~', ...args);
}
function getWinId(win) {
if ( !win ) return undefined;
var id = win.id;
if ( id ) return id;
win.id = getWinId._id = id = (getWinId._id||0) + 1;
return id;
}
function wait4url(tab, cb) {
var readyState;
return (function _wait() {
var url = tab.url;
// new tab's url is 'about:newtab'
if ( (url == 'about:blank' || !url) && (readyState = tab.readyState) != 'complete' && readyState != 'interactive' ) {
return setTimeout(_wait, 4);
}
cb(tab, url);
return url;
}())
}
Also save your patches of Tab
to setWindow.js
file.
With this test the detached window emits events, but earlier today while playing with code I’ve got in a situation where it didn’t. I guess becouse of an error right after .detatch
call.
setWindow()
behaves as described earlier, and there is an error in the console after detatch()
.
You can filter console output by “~” and follow events…