Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F35444430
enigmailprocess_worker_common.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
5 KB
Subscribers
None
enigmailprocess_worker_common.js
View Options
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict"
;
/* exported BasePipe, BaseProcess, debug */
/* globals Process, io */
/* global ctypes: false, onmessage: true */
/* eslint no-console: 0 */
function
debug
(
message
)
{
self
.
postMessage
({
msg
:
"debug"
,
message
});
}
class
BasePipe
{
constructor
()
{
this
.
closing
=
false
;
this
.
closed
=
false
;
this
.
closedPromise
=
new
Promise
(
resolve
=>
{
this
.
resolveClosed
=
resolve
;
});
this
.
pending
=
[];
}
shiftPending
()
{
let
result
=
this
.
pending
.
shift
();
if
(
this
.
closing
&&
this
.
pending
.
length
==
0
)
{
this
.
close
();
}
return
result
;
}
}
let
nextProcessId
=
0
;
class
BaseProcess
{
constructor
(
options
)
{
this
.
id
=
nextProcessId
++
;
this
.
exitCode
=
null
;
this
.
exitPromise
=
new
Promise
(
resolve
=>
{
this
.
resolveExit
=
resolve
;
});
this
.
exitPromise
.
then
(()
=>
{
// The input file descriptors will be closed after poll
// reports that their input buffers are empty. If we close
// them now, we may lose output.
this
.
pipes
[
0
].
close
(
true
);
});
this
.
pid
=
null
;
this
.
pipes
=
[];
this
.
stringArrays
=
[];
this
.
spawn
(
options
);
}
/**
* Waits for the process to exit and all of its pending IO operations to
* complete.
*
* @returns {Promise<void>}
*/
awaitFinished
()
{
return
Promise
.
all
([
this
.
exitPromise
,
...
this
.
pipes
.
map
(
pipe
=>
pipe
.
closedPromise
)
]);
}
/**
* Creates a null-terminated array of pointers to null-terminated C-strings,
* and returns it.
*
* @param {string[]} strings
* The strings to convert into a C string array.
*
* @returns {ctypes.char.ptr.array}
*/
stringArray
(
strings
)
{
let
result
=
ctypes
.
char
.
ptr
.
array
(
strings
.
length
+
1
)();
let
cstrings
=
strings
.
map
(
str
=>
ctypes
.
char
.
array
()(
str
));
for
(
let
[
i
,
cstring
]
of
cstrings
.
entries
())
{
result
[
i
]
=
cstring
;
}
// Char arrays used in char arg and environment vectors must be
// explicitly kept alive in a JS object, or they will be reaped
// by the GC if it runs before our process is started.
this
.
stringArrays
.
push
(
cstrings
);
return
result
;
}
}
let
requests
=
{
init
(
details
)
{
io
.
init
(
details
);
return
{
data
:
{}
};
},
shutdown
()
{
io
.
shutdown
();
return
{
data
:
{}
};
},
close
(
pipeId
,
force
=
false
)
{
let
pipe
=
io
.
getPipe
(
pipeId
);
return
pipe
.
close
(
force
).
then
(()
=>
({
data
:
{}
}));
},
spawn
(
options
)
{
let
process
=
new
Process
(
options
);
let
processId
=
process
.
id
;
io
.
addProcess
(
process
);
let
fds
=
process
.
pipes
.
map
(
pipe
=>
pipe
.
id
);
return
{
data
:
{
processId
,
fds
,
pid
:
process
.
pid
}
};
},
kill
(
processId
,
force
=
false
)
{
let
process
=
io
.
getProcess
(
processId
);
process
.
kill
(
force
?
9
:
15
);
return
{
data
:
{}
};
},
wait
(
processId
)
{
let
process
=
io
.
getProcess
(
processId
);
process
.
wait
();
process
.
awaitFinished
().
then
(()
=>
{
io
.
cleanupProcess
(
process
);
});
return
process
.
exitPromise
.
then
(
exitCode
=>
{
return
{
data
:
{
exitCode
}
};
});
},
read
(
pipeId
,
count
)
{
let
pipe
=
io
.
getPipe
(
pipeId
);
return
pipe
.
read
(
count
).
then
(
buffer
=>
{
return
{
data
:
{
buffer
}
};
});
},
write
(
pipeId
,
buffer
)
{
let
pipe
=
io
.
getPipe
(
pipeId
);
return
pipe
.
write
(
buffer
).
then
(
bytesWritten
=>
{
return
{
data
:
{
bytesWritten
}
};
});
},
getOpenFiles
()
{
return
{
data
:
new
Set
(
io
.
pipes
.
keys
())
};
},
getProcesses
()
{
let
data
=
new
Map
(
Array
.
from
(
io
.
processes
.
values
())
.
filter
(
proc
=>
proc
.
exitCode
===
null
)
.
map
(
proc
=>
[
proc
.
id
,
proc
.
pid
]));
return
{
data
};
},
waitForNoProcesses
()
{
return
Promise
.
all
(
Array
.
from
(
io
.
processes
.
values
(),
proc
=>
proc
.
awaitFinished
()));
}
};
onmessage
=
event
=>
{
io
.
messageCount
--
;
let
{
msg
,
msgId
,
args
}
=
event
.
data
;
new
Promise
(
resolve
=>
{
resolve
(
requests
[
msg
](...
args
));
}).
then
(
result
=>
{
let
response
=
{
msg
:
"success"
,
msgId
,
data
:
result
.
data
};
self
.
postMessage
(
response
,
result
.
transfer
||
[]);
}).
catch
(
error
=>
{
if
(
error
instanceof
Error
)
{
error
=
{
message
:
error
.
message
,
fileName
:
error
.
fileName
,
lineNumber
:
error
.
lineNumber
,
column
:
error
.
column
,
stack
:
error
.
stack
,
errorCode
:
error
.
errorCode
};
}
self
.
postMessage
({
msg
:
"failure"
,
msgId
,
error
});
}).
catch
(
error
=>
{
console
.
error
(
error
);
self
.
postMessage
({
msg
:
"failure"
,
msgId
,
error
:
{}
});
});
};
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Feb 8, 2:59 PM (5 h, 31 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d7/dd/4fdbe992f90bd4ac0510f8dee835
Attached To
rENIG Enigmail
Event Timeline
Log In to Comment