Skip to content
This repository has been archived by the owner on Aug 31, 2018. It is now read-only.

Commit

Permalink
worker: initial implementation
Browse files Browse the repository at this point in the history
Implement multi-threading support for most of the API.

PR-URL: #110
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
  • Loading branch information
addaleax committed Oct 22, 2017
1 parent 1ea4b76 commit fe685fb
Show file tree
Hide file tree
Showing 20 changed files with 1,067 additions and 70 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,4 @@ globals:
LTTNG_NET_SERVER_CONNECTION: false
LTTNG_NET_STREAM_END: false
internalBinding: false
isMainThread: false
5 changes: 5 additions & 0 deletions lib/domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

'use strict';

if (!isMainThread) {
const errors = require('internal/errors');
throw new errors.TypeError('ERR_WORKER_DOMAIN');
}

// WARNING: THIS MODULE IS PENDING DEPRECATION.
//
// No new pull requests targeting this module will be accepted
Expand Down
49 changes: 30 additions & 19 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

(function(process) {
let internalBinding;
let isMainThread;

function startup() {
const EventEmitter = NativeModule.require('events');
Expand All @@ -24,6 +25,8 @@
internalBinding = process._internalBinding;
delete process._internalBinding;

isMainThread = internalBinding('worker').threadId === 0;

// do this good and early, since it handles errors.
setupProcessFatal();

Expand Down Expand Up @@ -69,7 +72,7 @@

// Do not initialize channel in debugger agent, it deletes env variable
// and the main thread won't see it.
if (process.argv[1] !== '--debug-agent')
if (process.argv[1] !== '--debug-agent' && isMainThread)
_process.setupChannel();

_process.setupRawDebug();
Expand Down Expand Up @@ -110,8 +113,11 @@
// are running from a script and running the REPL - but there are a few
// others like the debugger or running --eval arguments. Here we decide
// which mode we run in.

if (NativeModule.exists('_third_party_main')) {
if (internalBinding('worker').getEnvMessagePort() !== undefined) {
// This means we are in a Worker context, and any script execution
// will be directed by the worker module.
NativeModule.require('internal/worker').setupChild(evalScript);
} else if (NativeModule.exists('_third_party_main')) {
// To allow people to extend Node in different ways, this hook allows
// one to drop a file lib/_third_party_main.js into the build
// directory which will be executed instead of Node's normal loading.
Expand Down Expand Up @@ -279,18 +285,20 @@
}, `'${name}' is deprecated, use 'global'`, 'DEP0016');
}

Object.defineProperties(global, {
GLOBAL: {
configurable: true,
get: makeGetter('GLOBAL'),
set: makeSetter('GLOBAL')
},
root: {
configurable: true,
get: makeGetter('root'),
set: makeSetter('root')
}
});
if (isMainThread) {
Object.defineProperties(global, {
GLOBAL: {
configurable: true,
get: makeGetter('GLOBAL'),
set: makeSetter('GLOBAL')
},
root: {
configurable: true,
get: makeGetter('root'),
set: makeSetter('root')
}
});
}

global.Buffer = NativeModule.require('buffer').Buffer;
process.domain = null;
Expand Down Expand Up @@ -446,15 +454,14 @@
return `process.binding('inspector').callAndPauseOnStart(${fn}, {})`;
}

function evalScript(name) {
function evalScript(name, body = wrapForBreakOnFirstLine(process._eval)) {
const Module = NativeModule.require('module');
const path = NativeModule.require('path');
const cwd = tryGetCwd(path);

const module = new Module(name);
module.filename = path.join(cwd, name);
module.paths = Module._nodeModulePaths(cwd);
const body = wrapForBreakOnFirstLine(process._eval);
const script = `global.__filename = ${JSON.stringify(name)};\n` +
'global.exports = exports;\n' +
'global.module = module;\n' +
Expand Down Expand Up @@ -578,7 +585,7 @@
};

NativeModule.wrapper = [
'(function (exports, require, module, internalBinding) {',
'(function (exports, require, module, internalBinding, isMainThread) {',
'\n});'
];

Expand All @@ -594,7 +601,11 @@
lineOffset: 0,
displayErrors: true
});
fn(this.exports, NativeModule.require, this, internalBinding);
fn(this.exports,
NativeModule.require,
this,
internalBinding,
isMainThread);

this.loaded = true;
} finally {
Expand Down
6 changes: 6 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ E('ERR_VALID_PERFORMANCE_ENTRY_TYPE',
E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => {
return `The value of "${start}" must be ${end}. Received "${value}"`;
});
E('ERR_WORKER_DOMAIN', 'Domains are not available inside worker threads');
E('ERR_WORKER_NEED_ABSOLUTE_PATH',
'The worker script filename must be an absolute path. Received "%s"');
E('ERR_WORKER_OUT_OF_MEMORY', 'The worker script ran out of memory');
E('ERR_WORKER_UNSERIALIZABLE_ERROR',
'Serializing an uncaught exception failed');
E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed');

function invalidArgType(name, expected, actual) {
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/process/stdio.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function setupStdio() {

function getStdout() {
if (stdout) return stdout;
if (!isMainThread) return null;
stdout = createWritableStdioStream(1);
stdout.destroySoon = stdout.destroy;
stdout._destroy = function(er, cb) {
Expand All @@ -26,6 +27,7 @@ function setupStdio() {

function getStderr() {
if (stderr) return stderr;
if (!isMainThread) return null;
stderr = createWritableStdioStream(2);
stderr.destroySoon = stderr.destroy;
stderr._destroy = function(er, cb) {
Expand All @@ -41,6 +43,7 @@ function setupStdio() {

function getStdin() {
if (stdin) return stdin;
if (!isMainThread) return null;

const tty_wrap = process.binding('tty_wrap');
const fd = 0;
Expand Down
Loading

0 comments on commit fe685fb

Please sign in to comment.