Limit action port message size (#587)
* Add onDisconnect handler * Update how error is posted * Update action ports to send long messages in fragments * Remove ack timer * Move message destructuring into try block
This commit is contained in:
parent
cfd3a1ec3a
commit
2c58b1c109
@ -861,6 +861,7 @@ class Backend {
|
||||
|
||||
_createActionListenerPort(port, sender, handlers) {
|
||||
let hasStarted = false;
|
||||
let messageString = '';
|
||||
|
||||
const onProgress = (...data) => {
|
||||
try {
|
||||
@ -871,12 +872,34 @@ class Backend {
|
||||
}
|
||||
};
|
||||
|
||||
const onMessage = async ({action, params}) => {
|
||||
const onMessage = (message) => {
|
||||
if (hasStarted) { return; }
|
||||
hasStarted = true;
|
||||
port.onMessage.removeListener(onMessage);
|
||||
|
||||
try {
|
||||
const {action, data} = message;
|
||||
switch (action) {
|
||||
case 'fragment':
|
||||
messageString += data;
|
||||
break;
|
||||
case 'invoke':
|
||||
{
|
||||
hasStarted = true;
|
||||
port.onMessage.removeListener(onMessage);
|
||||
|
||||
const messageData = JSON.parse(messageString);
|
||||
messageString = null;
|
||||
onMessageComplete(messageData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
cleanup(e);
|
||||
}
|
||||
};
|
||||
|
||||
const onMessageComplete = async (message) => {
|
||||
try {
|
||||
const {action, params} = message;
|
||||
port.postMessage({type: 'ack'});
|
||||
|
||||
const messageHandler = handlers.get(action);
|
||||
@ -893,25 +916,29 @@ class Backend {
|
||||
const result = async ? await promiseOrResult : promiseOrResult;
|
||||
port.postMessage({type: 'complete', data: result});
|
||||
} catch (e) {
|
||||
if (port !== null) {
|
||||
port.postMessage({type: 'error', data: errorToJson(e)});
|
||||
}
|
||||
cleanup();
|
||||
cleanup(e);
|
||||
}
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
const onDisconnect = () => {
|
||||
cleanup(null);
|
||||
};
|
||||
|
||||
const cleanup = (error) => {
|
||||
if (port === null) { return; }
|
||||
if (error !== null) {
|
||||
port.postMessage({type: 'error', data: errorToJson(error)});
|
||||
}
|
||||
if (!hasStarted) {
|
||||
port.onMessage.removeListener(onMessage);
|
||||
}
|
||||
port.onDisconnect.removeListener(cleanup);
|
||||
port.onDisconnect.removeListener(onDisconnect);
|
||||
port = null;
|
||||
handlers = null;
|
||||
};
|
||||
|
||||
port.onMessage.addListener(onMessage);
|
||||
port.onDisconnect.addListener(cleanup);
|
||||
port.onDisconnect.addListener(onDisconnect);
|
||||
}
|
||||
|
||||
_getErrorLevelValue(errorLevel) {
|
||||
|
@ -236,7 +236,6 @@ const api = (() => {
|
||||
|
||||
_invokeWithProgress(action, params, onProgress, timeout=5000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let timer = null;
|
||||
let port = null;
|
||||
|
||||
if (typeof onProgress !== 'function') {
|
||||
@ -245,12 +244,6 @@ const api = (() => {
|
||||
|
||||
const onMessage = (message) => {
|
||||
switch (message.type) {
|
||||
case 'ack':
|
||||
if (timer !== null) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
break;
|
||||
case 'progress':
|
||||
try {
|
||||
onProgress(...message.data);
|
||||
@ -275,10 +268,6 @@ const api = (() => {
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
if (timer !== null) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
if (port !== null) {
|
||||
port.onMessage.removeListener(onMessage);
|
||||
port.onDisconnect.removeListener(onDisconnect);
|
||||
@ -288,17 +277,20 @@ const api = (() => {
|
||||
onProgress = null;
|
||||
};
|
||||
|
||||
timer = setTimeout(() => {
|
||||
cleanup();
|
||||
reject(new Error('Timeout'));
|
||||
}, timeout);
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
port = await this._createActionPort(timeout);
|
||||
port.onMessage.addListener(onMessage);
|
||||
port.onDisconnect.addListener(onDisconnect);
|
||||
port.postMessage({action, params});
|
||||
|
||||
// Chrome has a maximum message size that can be sent, so longer messages must be fragmented.
|
||||
const messageString = JSON.stringify({action, params});
|
||||
const fragmentSize = 1e7; // 10 MB
|
||||
for (let i = 0, ii = messageString.length; i < ii; i += fragmentSize) {
|
||||
const data = messageString.substring(i, i + fragmentSize);
|
||||
port.postMessage({action: 'fragment', data});
|
||||
}
|
||||
port.postMessage({action: 'invoke'});
|
||||
} catch (e) {
|
||||
cleanup();
|
||||
reject(e);
|
||||
|
Loading…
Reference in New Issue
Block a user