Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
electron-re
Advanced tools
Test on electron@8.2.0 / 9.3.5
├── Contents (you are here!)
│
├── Architecture
│
├── * What can be used for?
│ ├── In Electron Project
│ └── In Nodejs/Electron Project
│
├── * Install
│
├── * Instruction1: ProcessManager
│ ├── Require it in main.js(electron)
│ └── Open process-manager window for your application
│
├── * Instruction2: Service
│ ├── The arguments to create a service
│ ├── Enable service auto reload after code changed
│ └── The methods of a Service instance
│
├── * Instruction3: MessageChannel
│ ├── The methods of MessageChannel
│ └── A full usage
│
├── * Instruction4: ChildProcessPool
│ ├── Create a childprocess pool
│ ├── Send request to a process instance
│ ├── Send request to all process instances
│ ├── Destroy the child processes of the process pool
│ └── Set the max instance limit of pool
│
├── * Instruction5: ProcessHost
│ ├── Require it in a sub process
│ ├── Registry a task with unique name
│ ├── Working with ChildProcessPool
│ └── Unregistry a task with unique name
│
├── * Instruction6: WorkerThreadPool
│ ├── Create a static WorkerThreadPool pool
│ ├── Create a static WorkerThreadPool excutor
│ ├── Create a dynamic WorkerThreadPool pool
│ └── Create a dynamic WorkerThreadPool excutor
│
├── Examples
BrowserServcie
to generate some service processes without UI and put your heavy tasks into them.MessageChannel
make it be possible to communicate with each other between main process
,render process
and service
.ProcessManager
provides a user interface for managing / monitoring processes, includes BrowserServcie
/ ChildProcess
/ renderer process
/ main process
.ChildProcessPool
with load-balancing support may helps when you need to create and manage several processes on nodejs runtime of electron.ProcessHost
let us be focused on the core sub-process logic rather than various async event.WorkerThreadPool
is effective for creating and managing threads.$: npm install electron-re --save
# or
$: yarn add electron-re --save
Used in Electron project, build for ChildProcessPool/BrowserService.
Compatible with native IpcRenderer/Main.
All functions:
Show all alive processes in your Electron application: main process, renderer process, the service process (imported by electron-re), and the child process created by ChildProcessPool (imported by electron-re).
The process list displays info: process ID, process type(mark), parent process ID, memory, CPU. All processes type include main (main process), service (service process), renderer (renderer process) , node (child process in process pool). click on table header to sort an item in increasing/decreasing order.
You can kill a process, view process console data, check CPU/memory occupancy within 1 min.
If a process marked as renderer, pressing the DevTools
button then the built-in debugging tool will open as an undocked window. Besides the child-processes are created by ChildProcessPool with --inspect
parameter, DevTools is not supported, just visit chrome://inspect
in chrome for remote debugging.
Try to use MessageChannel
for sending/receiving ipc messages, there is a ui pannel area that show activities of it (logger).
const {
MessageChannel, // remember to require it in main.js even if you don't use it
ProcessManager
} = require('electron-re');
ProcessManager.openWindow();
The main ui
Show console info of all processes
Open devtools for electron renderer window
Show cpu/memory occupancy trends
Kill process from one-click
Activities logger for
MessageChannel
tool
Used in Electron project, working with MessageChannel, remember to check "Instruction 3".
The service
process is a customized render process that works in the background, receiving path
, options
as arguments:
new BrowserWindow()
options./* --- main.js --- */
const { BrowserService } = require('electron-re');
const myService = new BrowserService('app', 'path/to/app.service.js', options);app.service.js'));
The auto-reload
feature is based on nodejs - fs.watch
api. When webSecurity closed and in dev
mode, service will reload when service code changed.
1.Set dev mode in new BrowserService()
options
2.Get webSecurity closed
/* --- main.js --- */
const myService = new BrowserService('app', 'path/to/app.service.js', {
...options,
// set dev mode with webSecurity closed
dev: true,
webPreferences: { webSecurity: false }
});
The service instance is a customized BrowserWindow
instance too, initialized by a file worked with commonJs
module, so you can use require('name')
and can't use import some from 'name'
syntax. It has two extension methods:
connected()
- return a resolved Promise
when service is ready.openDevTools
- open an undocked window for debugging.suggest to put some business-related code into a service.
/* --- main.js --- */
const {
BrowserService,
MessageChannel // must required in main.js even if you don't use it
} = require('electron-re');
...
app.whenReady().then(async() => {
// after app is ready in main process
const myService = new BrowserService('app', 'path/to/app.service.js');
// async
await myService.connected();
mhyService.openDevTools();
/* work with webContents method, also you can use MessageChannel instead */
mhyService.webContents.send('channel1', { value: 'test1' });
});
...
/* --- app.service.js --- */
const { ipcRenderer } = require('electron');
/* working with ipc method, also you can use MessageChannel instead */
ipcRenderer.on('channel1', (event, result) => {
// works
...
});
Used in Electron project, working with Service.
When sending data from main/other process to a service you need to use MesssageChannel
, such as: MessageChannel.send('service-name', 'channel', 'params')
, And also it can be used to replace other build-in ipc
methods, more flexible.
1.Public methods,used in Main-Pocess / Renderer-Process / Service
/* send data to a service - like the build-in ipcMain.send */
MessageChannel.send('service-name', channel, params);
/* send data to a service and return a Promise - extension method */
MessageChannel.invoke('service-name', channel, params);
/*
send data to a renderer/servcie which id is same as the given windowId/webContentsId,
same as ipcRenderer.sendTo,
recommend to use it when you want to send data from main/service to a renderer window
*/
MessageChannel.sendTo('windowId/webContentsId', channel, params);
/* listen a channel, same as ipcMain.on/ipcRenderer.on */
MessageChannel.on(channel, func);
/* listen a channel once, same as ipcMain.once/ipcRenderer.once */
MessageChannel.once(channel, func);
2.Only used in Renderer-process / Service
/* send data to main process - like the build-in ipcRender.send */
MessageChannel.send('main', channel, params);
/* send data to main process and return a Promise - extension method */
MessageChannel.invoke('main', channel, params);
3.Only used in Main-process / Service
/*
handle a channel signal, extension method,
and you can return data directly or return a Promise instance
*/
MessageChannel.handle(channel, processorFunc);
const {
BrowserService,
MessageChannel // must required in main.js even if you don't use it
} = require('electron-re');
const isInDev = process.env.NODE_ENV === 'dev';
...
/* use MessageChannel instead of build-in method */
app.whenReady().then(() => {
const myService = new BrowserService('app', 'path/to/app.service.js');
myService.connected().then(() => {
// open devtools in dev mode for debugging
if (isInDev) myService.openDevTools();
MessageChannel.send('app', 'channel1', { value: 'test1' });
MessageChannel.invoke('app', 'channel2', { value: 'test2' }).then((response) => {
console.log(response);
});
MessageChannel.on('channel3', (event, response) => {
console.log(response);
});
MessageChannel.handle('channel4', (event, response) => {
console.log(response);
return { res: 'channel4-res' };
});
})
});
const { ipcRenderer } = require('electron');
const { MessageChannel } = require('electron-re');
MessageChannel.on('channel1', (event, result) => {
console.log(result);
});
MessageChannel.handle('channel2', (event, result) => {
console.log(result);
return { response: 'channel2-response' }
});
MessageChannel.invoke('app2', 'channel3', { value: 'channel3' }).then((event, result) => {
console.log(result);
});
MessageChannel.send('app2', 'channel4', { value: 'channel4' });
MessageChannel.handle('channel3', (event, result) => {
console.log(result);
return { response: 'channel3-response' }
});
MessageChannel.once('channel4', (event, result) => {
console.log(result);
});
MessageChannel.send('main', 'channel3', { value: 'channel3' });
MessageChannel.send('main', 'channel3', { value: 'channel3' });
MessageChannel.invoke('main', 'channel4', { value: 'channel4' });
const { ipcRenderer } = require('electron');
const { MessageChannel } = require('electron-re');
MessageChannel.send('app', 'channel1', { value: 'test1'});
MessageChannel.invoke('app2', 'channel3', { value: 'test2' });
MessageChannel.send('main', 'channel3', { value: 'test3' });
MessageChannel.invoke('main', 'channel4', { value: 'test4' });
Used in Nodejs/Electron project, working with ProcessHost, remember to check "Instruction 5".
Multi-process helps to make full use of multi-core CPU, let's see some differences between multi-process and multi-thread:
DO NOT USE require('electron')
in child_process js exec file, this will cause fatal error in the production environment!
Besides that, In order to use ChildProcessPool, you need to place your child_process exec js file in an external directory such as ~/.config/
. Otherwise, when you packaged your app, Node.js can not find that exec file.
The another way to solve this problem is to set asar
to false in the electron-builder.json, this is not recommended but works.
{
...
"asar": false,
...
}
POLLING
.
WEIGHTS
.WEIGHTS
.WEIGHTS
.const { ChildProcessPool, LoadBalancer } = require('electron-re');
global.ipcUploadProcess = new ChildProcessPool({
path: path.join(app.getAppPath(), 'app/services/child/upload.js'),
max: 3,
env: { lang: global.lang, NODE_ENV: nodeEnv },
strategy: LoadBalancer.ALGORITHM.WEIGHTS_POLLING, // loadbalance strategy
weights: [1, 2, 3],
});
ProcessHost
.send()
).send
function, each time pool will send a request to the process bound with this id.global.ipcUploadProcess.send(
'init-works',
{
name: 'fileName',
type: 'fileType',
size: 'fileSize',
},
'id-number' // optional and it's given by you
)
.then((rsp) => {
console.log(rsp);
});
All sub processes will receive a request, and you can get a response data array from all sub processes.
ProcessHost
(check usage below).global.ipcUploadProcess.sendToAll(
'task-get-all',
{ key: 'test' }
)
.then((rsp) => {
console.log(rsp);
});
If do not specify id
, all child processes will be destroyed. Specifying the id
parameter can separately destroy a child process bound to this id
.
After the destruction, using the process pool to send a new request, a new child process will be created automatically.
It should be noted that the id
binding operation is automatically performed after the processPool.send('task-name', params, id)
method is called.
// destroy a process with id value
global.ipcUploadProcess.disconnect(id);
// destroy all processes
global.ipcUploadProcess.disconnect();
In addition to using the max
parameter to specify the maximum number of child process instances created by the process pool, you can also call this method to dynamically set the number of child process instances that need to be created.
global.ipcUploadProcess.setMaxInstanceLimit(number);
Used in Nodejs/Electron project, working with ChildProcessPool.
In Instruction 4
, We already know how to create a sub-process pool and send request using it. Now let's figure out how to registry a task and handle process messages in a sub process(created by ChildProcessPool constructor with param - path
).
Using ProcessHost
we will no longer pay attention to the message sending/receiving between main process and sub processes. Just declaring a task with a unique service-name and put your processing code into a function. And remember that if the code is async, return a Promise instance instead.
const { ProcessHost } = require('electron-re');
Support chain call
ProcessHost
.registry('init-works', (params) => {
return initWorks(params);
})
.registry('async-works', (params) => {
return asyncWorks(params);
});
function initWorks(params) {
console.log(params);
return params;
}
function asyncWorks(params) {
console.log(params);
return fetch(url);
}
ChildProcessPool
/* 1. send a request in main process */
global.ipcUploadProcess.send(
'init-works',
{
name: 'fileName',
type: 'fileType',
size: 'fileSize',
}
);
...
/* 2. handle this request in sub process */
...
Support chain call
ProcessHost
.unregistry('init-works')
.unregistry('async-works')
...
Multi Processes help to make full use of cpu, Multi Threads improve task parallelism ability of Node.js.
In Node.js, there is only one main process which has single main thread, the main thread run event loops and executes macro/micro tasks. In theory, macro/micro task should be short and quick, if we use main thread for some cpu-sensitive heavy tasks, this will block event loop on main thread.
So, try to put your heavy tasks into worker threads will be better in Node.js. The worker thread pool is effective for creating and managing threads, besides, it provides a task queue. When pool has no idle thread, more coming tasks are placed in queue and be taken out from queue after while to be excuted by new idle thread.
constructor(options, threadOptions)
opitons
: the options to create a static thread pool:
execPath
{String}: path to an executable commonjs module file.execString
{String}: executable code string.execFunction
{Function}: js function.lazyLoad
{Boolean}: if diabled, all threads will be created when init pool.maxThreads
{Number}: max thread count of pool.maxTasks
{Number}: max task count of pool.taskRetry
{Number}: number of task retries.taskLoopTime
{Number}: time of task loop.taskTimeout
{Number}: timeout time.threadOpitions
: Some origin options for node.js worker_threads.
transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
const staticPool = new StaticThreadPool(
{
// execPath: 'path/to/executable.js',
execString: 'module.exports = (payload) => `res:${payload}`',
// execFunction: (payload) => payload,
lazyLoad: true,
maxThreads: 24,
maxTasks: 48,
taskRetry: 1,
taskLoopTime: 1e3,
taskTimeout: 5e3,
},
{
transferList: [uint8Array.buffer]
}
);
isFull
{Boolean}: whether the pool is full of threads, related to this param - maxThreads.threadLength
{Number}: current thread count of pool.taskLength
{Number}: current task count of pool.fillPoolWithIdleThreads()
: fill pool with idle threads, this is effective when pool is not full.queue(payload, options)
: Save a task request to task queue, will throw an error when the task queue is full.
payload
*: The request payload data.options
: Options to create a task:
taskTimeout
:The task timeout in millisecondstaskRetry
:Number of task retries.transferList
: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.exec(payload, options)
: Send a task request to pool, will throw an error when there is no idle thread and the task queue is full.
payload
*: The request payload data.options
: Options to create a task:
taskTimeout
:The task timeout in millisecondstaskRetry
:Number of task retries.transferList
: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.createExecutor(options={})
: Create an static executor to execute tasks.
options
: Options to create a executor:
taskTimeout
:The task timeout in millisecondstaskRetry
:Number of task retries.transferList
: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.wipeTaskQueue()
: Wipe all tasks in queue.wipeThreadPool()
: Wipe all threads in pool.setMaxThreads(maxThreads)
: Set max thread count of pool.
maxThreads
:max thread count.setMaxTasks(maxTasks)
: Set max task count of pool.
maxTasks
:max task count.setTaskLoopTime(taskLoopTime)
: Set time of task loop.
taskLoopTime
:task loop time.setTaskRetry(taskRetry)
: Set count of task retries.
taskRetry
:Number of task retries.setTransferList(transferList)
: Set transfer-list data of task.
transferList
:transfer-list data.staticPool
.setTaskRetry(1)
.exec('payload-data', {
taskTimeout: 5e3,
taskRetry: 1,
})
.then((rsp) => {
console.log(rsp);
});
taskRetry
{Number}: number of task retries.taskTimeout
{Number}: timeout time.transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
const staticExecutor = staticPool.createExecutor({
taskRetry: 2,
taskTimeout: 2e3,
transferList: [unit8Array.buffer]
});
queue(payload, options)
: Save a task request to task queue, will throw an error when the task queue is full.
payload
*: The request payload data.exec(payload)
: Send a task request to pool from excutor.
payload
*: The request payload data.setTaskRetry(taskRetry)
: Set count of task retries.
taskRetry
:Number of task retries.setTransferList(transferList)
: Set transfer-list data of task.
transferList
:transfer-list data.setTaskTimeout(taskTimeout)
: Set timeout time of task.
taskTimeout
:timeout time.staticExecutor
.setTaskRetry(2)
.exec('test')
.then((rsp) => {
console.log(rsp);
});
constructor(options, threadOptions)
opitions
: the options to create a static thread pool:
maxThreads
{Number}: max thread count of pool.maxTasks
{Number}: max task count of pool.taskRetry
{Number}: number of task retries.taskLoopTime
{Number}: time of task loop.taskTimeout
{Number}: timeout time.threadOptions
: Some origin options for node.js worker_threads.
transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.const dynamicPool = new DynamicThreadPool({
maxThreads: 24,
maxTasks: 48,
taskRetry: 1,
taskLoopTime: 1e3,
taskTimeout: 5e3,
});
isFull
{Boolean}: whether the pool is full of threads, related to this param - maxThreads.threadLength
{Number}: current thread count of pool.taskLength
{Number}: current task count of pool.queue(payload, options)
: Save a task request to task queue, will throw an error when the task queue is full.
payload
*: The request payload data.options
: Options to create a task:
execPath
{String}: path to an executable commonjs module file.execString
{String}: executable code string.execFunction
{Function}: js function.taskTimeout
:The task timeout in millisecondstaskRetry
:Number of task retries.transferList
: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.exec(payload, options)
: Send a task request to pool, will throw an error when there is no idle thread and the task queue is full.
payload
*: The request payload data.options
: Options to create a task:
execPath
{String}: path to an executable commonjs module file.execString
{String}: executable code string.execFunction
{Function}: js function.taskTimeout
{Number}:The task timeout in millisecondstaskRetry
{Number}:Number of task retries.transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.createExecutor(options={})
: Create a dynamic executor to execute tasks.
options
: Options to create a executor:
execPath
{String}: path to an executable commonjs module file.execString
{String}: executable code string.execFunction
{Function}: js function.taskTimeout
{Number}:The task timeout in millisecondstaskRetry
{Number}:Number of task retries.transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.wipeTaskQueue()
: Wipe all tasks in queue.wipeThreadPool()
: Wipe all threads in pool.setMaxThreads(maxThreads)
: Set max thread count of pool.
maxThreads
:max thread count.setMaxTasks(maxTasks)
: Set max task count of pool.
maxTasks
:max task count.setTaskLoopTime(taskLoopTime)
: Set time of task loop.
taskLoopTime
:task loop time.setTaskRetry(taskRetry)
: Set count of task retries.
taskRetry
:Number of task retries.setTransferList(transferList)
: Set transfer-list data of task.
transferList
:transfer-list data.setExecPath(execPath)
: Set path of an executable commonjs module file.
execPath
:path to an executable commonjs module file.setExecString(execString)
: Set executable code string.
execString
:executable code string.setExecFunction(execFunction)
: Set js function.
execFunction
:js function.dynamicPool
.setExecString(`module.exports = (payload) => console.log(payload);`)
.setTaskRetry(1)
.exec('payload-data', {
taskTimeout: 5e3,
taskRetry: 1,
})
.then((rsp) => {
console.log(rsp);
});
execPath
{String}: path to an executable commonjs module file.execString
{String}: executable code string.execFunction
{Function}: js function.taskRetry
{Number}: number of task retries.taskTimeout
{Number}: timeout time.transferList
{Array}: A list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side.const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
const dynamicExecutor = dynamicPool.createExecutor({
execString: `module.exports = (payload) => payload`,
// execFunction: (payload) => payload,
// execPath: 'path/to/executable.js',
taskRetry: 2,
taskTimeout: 2e3,
transferList: [unit8Array.buffer]
});
setExecPath(execPath)
: Set path of an executable commonjs module file.
execPath
:path to an executable commonjs module file.setExecString(execString)
: Set executable code string.
execString
:executable code string.setExecFunction(execFunction)
: Set js function.
execFunction
:js function.queue(payload)
: Save a task request to task queue, will throw an error when the task queue is full.
payload
*: The request payload data.exec(payload)
: Send a task request to pool from excutor.
payload
*: The request payload data.setTaskRetry(taskRetry)
: Set count of task retries.
taskRetry
:Number of task retries.setTransferList(transferList)
: Set transfer-list data of task.
transferList
:transfer-list data.setExecPath(execPath)
: Set path of an executable commonjs module file.electronux - A project of mine that uses BroserService
and MessageChannel
of electron-re.
file-slice-upload - A demo about parallel upload of multiple files, it uses ChildProcessPool
and ProcessHost
of electron-re, based on Electron@9.3.5.
Also you can check the index.dev.js
and test
dir in root, there are some useful cases.
------------------------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------
All files | 75.27 | 55.73 | 68.15 | 79.29 |
lib | 96.42 | 66.66 | 100 | 96.42 |
index.js | 96.42 | 66.66 | 100 | 96.42 | 23
lib/libs | 66.83 | 44.61 | 59.12 | 72.59 |
BrowserService.class.js | 76.99 | 55.26 | 55.17 | 77.22 | 61-64,69-92,106-108,172,184-185,191,209-210,231,235
EventCenter.class.js | 80 | 58.33 | 83.33 | 100 | 15-35
FileWatcher.class.js | 60 | 41.66 | 42.85 | 66.66 | 29-49
MessageChannel.class.js | 52.11 | 32.35 | 46.8 | 58.49 | 60-61,75-256,292-297,312-313,394-409,540-547
ProcessHost.class.js | 70.73 | 35.71 | 62.5 | 76.31 | 27,51-59,80,92-108
ProcessLifeCycle.class.js | 88.46 | 67.64 | 94.11 | 98.36 | 95
consts.js | 100 | 100 | 100 | 100 |
utils.js | 65.16 | 45.83 | 60 | 68.67 | 75-93,107-114,120-131,180,188
lib/libs/ChildProcessPool | 84.84 | 62 | 80 | 89.91 |
ForkedProcess.js | 78.33 | 50 | 72.72 | 82.45 | 22,64-75,97,103-105
index.js | 86.76 | 65.78 | 82.35 | 92.39 | 119,141,219-223,231-233,287,306-315
lib/libs/LoadBalancer | 80.29 | 50 | 84.37 | 80.91 |
consts.js | 100 | 100 | 100 | 100 |
index.js | 77.58 | 50 | 82.14 | 78.18 | 63-69,83,97,103,113,126,153,158-162,178-193,203
scheduler.js | 95 | 50 | 100 | 95 | 28
lib/libs/LoadBalancer/algorithm | 94.79 | 67.3 | 100 | 100 |
MINIMUM_CONNECTION.js | 92.3 | 64.28 | 100 | 100 | 5-6,19
POLLING.js | 85.71 | 50 | 100 | 100 | 5-9
RANDOM.js | 100 | 50 | 100 | 100 | 7
SPECIFY.js | 100 | 75 | 100 | 100 | 14
WEIGHTS.js | 92.85 | 66.66 | 100 | 100 | 5-11
WEIGHTS_MINIMUM_CONNECTION.js | 94.11 | 80 | 100 | 100 | 5,15
WEIGHTS_POLLING.js | 92.3 | 66.66 | 100 | 100 | 5-10
WEIGHTS_RANDOM.js | 100 | 66.66 | 100 | 100 | 9,17
index.js | 100 | 100 | 100 | 100 |
lib/libs/ProcessManager | 51.08 | 25 | 38.46 | 51.77 |
index.js | 57.21 | 31.39 | 48 | 58.6 | 66,71,76,81,110,123,132,143,150-169,175-224,228-230,236-245,285-287,295-298,303-306,311-336
ui.js | 32.35 | 0 | 6.66 | 32.83 | 34-122,130-137
lib/libs/WorkerThreadPool | 81.52 | 57.5 | 78 | 84.72 |
Task.js | 85.36 | 83.33 | 61.53 | 85.36 | 44-45,77-92
TaskQueue.js | 66.19 | 39.28 | 86.66 | 69.23 | 78-79,98-139
Thread.js | 85 | 64.7 | 80 | 91.78 | 61-63,150-156,165
consts.js | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
utils.js | 91.66 | 50 | 100 | 91.66 | 23
lib/libs/WorkerThreadPool/Executor | 81.53 | 67.5 | 80.76 | 89.79 |
DynamicExecutor.js | 76.66 | 71.42 | 75 | 84.09 | 50-53,66-67,97
Executor.js | 93.75 | 66.66 | 100 | 93.75 | 70,74
StaticExecutor.js | 78.94 | 60 | 75 | 95.45 | 39
lib/libs/WorkerThreadPool/Pool | 83.37 | 72.41 | 81.01 | 87.95 |
DynamicThreadPool.js | 82.5 | 66.12 | 76.47 | 90.56 | 87-89,129,141
StaticThreadPool.js | 87.69 | 70.83 | 92.85 | 97.95 | 144
ThreadPool.js | 82.57 | 75.49 | 79.16 | 85.21 | 116-118,144-145,165,213-214,224,256-258,356,494-533,564,568,572,576,587
lib/libs/WorkerThreadPool/Worker | 77.35 | 60 | 62.5 | 81.01 |
index.js | 84.28 | 67.85 | 76.47 | 95.34 | 49,73
worker-runner.js | 63.88 | 41.66 | 28.57 | 63.88 | 19-22,32,36-42,54-59,65,76
lib/tasks | 83.33 | 50 | 100 | 88.23 |
app.init.js | 83.33 | 50 | 100 | 88.23 | 33-39
------------------------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------
FAQs
Electron Process Manager
The npm package electron-re receives a total of 39 weekly downloads. As such, electron-re popularity was classified as not popular.
We found that electron-re demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.