pad: Fix initialization race condition

Ensure that `padeditbar.init()` is called before setting up
`pad.collabClient` to avoid the following exception when there is an
error connecting:

    TypeError: Cannot read property 'length' of undefined
        at Object.toggleDropDown
        at Object.showModal
        at Object.disconnected
        at r.<anonymous>
        at r.emit
        at r.onevent
        at r.onpacket
        at r.<anonymous>
        at r.emit
        at r.ondecoded
This commit is contained in:
Richard Hansen 2021-03-30 19:55:35 -04:00
parent a18f5de0fc
commit 8ef84e5350

View file

@ -283,7 +283,7 @@ const handshake = () => {
// just annoys users and fills logs. // just annoys users and fills logs.
}); });
socket.on('message', (obj) => { socket.on('message', async (obj) => {
// the access was not granted, give the user a message // the access was not granted, give the user a message
if (obj.accessStatus) { if (obj.accessStatus) {
if (obj.accessStatus === 'deny') { if (obj.accessStatus === 'deny') {
@ -304,7 +304,7 @@ const handshake = () => {
window.clientVars = obj.data; window.clientVars = obj.data;
// initialize the pad // initialize the pad
pad._afterHandshake(); await pad._afterHandshake();
if (clientVars.readonly) { if (clientVars.readonly) {
chat.hide(); chat.hide();
@ -444,7 +444,7 @@ const pad = {
padcookie.init(); padcookie.init();
}); });
}, },
_afterHandshake() { async _afterHandshake() {
pad.clientTimeOffset = Date.now() - clientVars.serverTimestamp; pad.clientTimeOffset = Date.now() - clientVars.serverTimestamp;
// initialize the chat // initialize the chat
chat.init(this); chat.init(this);
@ -461,8 +461,37 @@ const pad = {
colorId: clientVars.userColor, colorId: clientVars.userColor,
}; };
const postAceInit = () => { padimpexp.init(this);
padsavedrevs.init(this);
paduserlist.init(pad.myUserInfo, this);
padconnectionstatus.init();
padmodals.init(this);
// padeditor.init() should be called late because it hides #editorloadingbox, which tests use as
// a signal that the pad is ready.
await padeditor.init(pad.padOptions.view || {}, this);
padeditbar.init(); padeditbar.init();
pad.collabClient = getCollabClient(
padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo,
{colorPalette: pad.getColorPalette()}, pad);
pad.collabClient.setOnUserJoin(pad.handleUserJoin);
pad.collabClient.setOnUpdateUserInfo(pad.handleUserUpdate);
pad.collabClient.setOnUserLeave(pad.handleUserLeave);
pad.collabClient.setOnClientMessage(pad.handleClientMessage);
pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange);
pad.collabClient.setOnInternalAction(pad.handleCollabAction);
pad.collabClient.setChannelState('CONNECTED');
// load initial chat-messages
if (clientVars.chatHead !== -1) {
const chatHead = clientVars.chatHead;
const start = Math.max(chatHead - 100, 0);
pad.collabClient.sendMessage({type: 'GET_CHAT_MESSAGES', start, end: chatHead});
} else {
// there are no messages
$('#chatloadmessagesbutton').css('display', 'none');
}
setTimeout(() => { setTimeout(() => {
padeditor.ace.focus(); padeditor.ace.focus();
}, 0); }, 0);
@ -501,37 +530,7 @@ const pad = {
$('#editorcontainer').addClass('initialized'); $('#editorcontainer').addClass('initialized');
hooks.aCallAll('postAceInit', {ace: padeditor.ace, clientVars, pad}); await hooks.aCallAll('postAceInit', {ace: padeditor.ace, clientVars, pad});
};
// order of inits is important here:
padimpexp.init(this);
padsavedrevs.init(this);
padeditor.init(pad.padOptions.view || {}, this).then(postAceInit);
paduserlist.init(pad.myUserInfo, this);
padconnectionstatus.init();
padmodals.init(this);
pad.collabClient = getCollabClient(
padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo,
{colorPalette: pad.getColorPalette()}, pad);
pad.collabClient.setOnUserJoin(pad.handleUserJoin);
pad.collabClient.setOnUpdateUserInfo(pad.handleUserUpdate);
pad.collabClient.setOnUserLeave(pad.handleUserLeave);
pad.collabClient.setOnClientMessage(pad.handleClientMessage);
pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange);
pad.collabClient.setOnInternalAction(pad.handleCollabAction);
pad.collabClient.setChannelState('CONNECTED');
// load initial chat-messages
if (clientVars.chatHead !== -1) {
const chatHead = clientVars.chatHead;
const start = Math.max(chatHead - 100, 0);
pad.collabClient.sendMessage({type: 'GET_CHAT_MESSAGES', start, end: chatHead});
} else {
// there are no messages
$('#chatloadmessagesbutton').css('display', 'none');
}
}, },
dispose: () => { dispose: () => {
padeditor.dispose(); padeditor.dispose();