Skip to content

Commit

Permalink
Merge pull request #1 from nodejs/master
Browse files Browse the repository at this point in the history
merge remote repo
  • Loading branch information
tonyhty authored Apr 28, 2019
2 parents 92c2544 + 757f3f8 commit 8bb3445
Show file tree
Hide file tree
Showing 29 changed files with 396 additions and 58 deletions.
59 changes: 59 additions & 0 deletions benchmark/misc/print.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';
const common = require('../common.js');
const { spawn } = require('child_process');

const bench = common.createBenchmark(main, {
dur: [1],
code: ['1', '"string"', 'process.versions', 'process']
});

function spawnProcess(code) {
const cmd = process.execPath || process.argv[0];
const argv = ['-p', code];
return spawn(cmd, argv);
}

function start(state, code, bench, getNode) {
const node = getNode(code);
let stdout = '';
let stderr = '';

node.stdout.on('data', (data) => {
stdout += data;
});

node.stderr.on('data', (data) => {
stderr += data;
});

node.on('exit', (code) => {
if (code !== 0) {
console.error('------ stdout ------');
console.error(stdout);
console.error('------ stderr ------');
console.error(stderr);
throw new Error(`Error during node startup, exit code ${code}`);
}
state.throughput++;

if (state.go) {
start(state, code, bench, getNode);
} else {
bench.end(state.throughput);
}
});
}

function main({ dur, code }) {
const state = {
go: true,
throughput: 0
};

setTimeout(() => {
state.go = false;
}, dur * 1000);

bench.start();
start(state, code, bench, spawnProcess);
}
20 changes: 2 additions & 18 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ const {
validateOffsetLengthRead,
validateOffsetLengthWrite,
validatePath,
warnOnNonPortableTemplate
warnOnNonPortableTemplate,
handleErrorFromBinding
} = require('internal/fs/utils');
const {
CHAR_FORWARD_SLASH,
Expand Down Expand Up @@ -117,23 +118,6 @@ function showTruncateDeprecation() {
}
}

function handleErrorFromBinding(ctx) {
if (ctx.errno !== undefined) { // libuv error numbers
const err = uvException(ctx);
// eslint-disable-next-line no-restricted-syntax
Error.captureStackTrace(err, handleErrorFromBinding);
throw err;
}
if (ctx.error !== undefined) { // Errors created in C++ land.
// TODO(joyeecheung): currently, ctx.error are encoding errors
// usually caused by memory problems. We need to figure out proper error
// code(s) for this.
// eslint-disable-next-line no-restricted-syntax
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
throw ctx.error;
}
}

function maybeCallback(cb) {
if (typeof cb === 'function')
return cb;
Expand Down
22 changes: 21 additions & 1 deletion lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const {
ERR_INVALID_OPT_VALUE_ENCODING,
ERR_OUT_OF_RANGE
},
hideStackFrames
hideStackFrames,
uvException
} = require('internal/errors');
const {
isUint8Array,
Expand Down Expand Up @@ -444,7 +445,26 @@ function warnOnNonPortableTemplate(template) {
}
}

// This handles errors following the convention of the fs binding.
function handleErrorFromBinding(ctx) {
if (ctx.errno !== undefined) { // libuv error numbers
const err = uvException(ctx);
// eslint-disable-next-line no-restricted-syntax
Error.captureStackTrace(err, handleErrorFromBinding);
throw err;
}
if (ctx.error !== undefined) { // Errors created in C++ land.
// TODO(joyeecheung): currently, ctx.error are encoding errors
// usually caused by memory problems. We need to figure out proper error
// code(s) for this.
// eslint-disable-next-line no-restricted-syntax
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
throw ctx.error;
}
}

module.exports = {
handleErrorFromBinding,
assertEncoding,
copyObject,
Dirent,
Expand Down
10 changes: 4 additions & 6 deletions lib/internal/main/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const {
evalScript
} = require('internal/process/execution');

const console = require('internal/console/global');
const { print, kStderr, kStdout } = require('internal/util/print');

const { getOptionValue } = require('internal/options');

Expand All @@ -21,14 +21,12 @@ markBootstrapComplete();

// --input-type flag not supported in REPL
if (getOptionValue('--input-type')) {
// If we can't write to stderr, we'd like to make this a noop,
// so use console.error.
console.error('Cannot specify --input-type for REPL');
print(kStderr, 'Cannot specify --input-type for REPL');
process.exit(1);
}

console.log(`Welcome to Node.js ${process.version}.\n` +
'Type ".help" for more information.');
print(kStdout, `Welcome to Node.js ${process.version}.\n` +
'Type ".help" for more information.');

const cliRepl = require('internal/repl');
cliRepl.createInternalRepl(process.env, (err, repl) => {
Expand Down
4 changes: 0 additions & 4 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -819,13 +819,9 @@ Module.runMain = function() {
true /* fromPromise */
);
});
// Handle any nextTicks added in the first tick of the program
process._tickCallback();
return;
}
Module._load(process.argv[1], null, true);
// Handle any nextTicks added in the first tick of the program
process._tickCallback();
};

Module.createRequireFromPath = (filename) => {
Expand Down
22 changes: 8 additions & 14 deletions lib/internal/process/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,22 @@ function tryGetCwd() {
}
}

function evalModule(source, print) {
const { log, error } = require('internal/console/global');
function evalModule(source, printResult) {
const { decorateErrorStack } = require('internal/util');
const asyncESM = require('internal/process/esm_loader');
const { kStdout, kStderr, print } = require('internal/util/print');
asyncESM.loaderPromise.then(async (loader) => {
const { result } = await loader.eval(source);
if (print) {
log(result);
}
if (printResult) { print(kStdout, result); }
})
.catch((e) => {
decorateErrorStack(e);
error(e);
print(kStderr, e);
process.exit(1);
});
// Handle any nextTicks added in the first tick of the program.
process._tickCallback();
}

function evalScript(name, body, breakFirstLine, print) {
function evalScript(name, body, breakFirstLine, printResult) {
const CJSModule = require('internal/modules/cjs/loader');
const { kVmBreakFirstLineSymbol } = require('internal/util');

Expand All @@ -79,12 +75,10 @@ function evalScript(name, body, breakFirstLine, print) {
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
});\n`;
const result = module._compile(script, `${name}-wrapper`);
if (print) {
const { log } = require('internal/console/global');
log(result);
if (printResult) {
const { kStdout, print } = require('internal/util/print');
print(kStdout, result);
}
// Handle any nextTicks added in the first tick of the program.
process._tickCallback();
}

const exceptionHandlerState = { captureFn: null };
Expand Down
1 change: 1 addition & 0 deletions lib/internal/process/task_queues.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function setHasTickScheduled(value) {

const queue = new FixedQueue();

// Should be in sync with RunNextTicksNative in node_task_queue.cc
function runNextTicks() {
if (!hasTickScheduled() && !hasRejectionToWarn())
runMicrotasks();
Expand Down
67 changes: 67 additions & 0 deletions lib/internal/util/print.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

// This implements a light-weight printer that writes to stdout/stderr
// directly to avoid the overhead in the console abstraction.

const { formatWithOptions } = require('internal/util/inspect');
const { writeString } = internalBinding('fs');
const { handleErrorFromBinding } = require('internal/fs/utils');
const { guessHandleType } = internalBinding('util');
const { log } = require('internal/console/global');

const kStdout = 1;
const kStderr = 2;
const handleType = [undefined, undefined, undefined];
function getFdType(fd) {
if (handleType[fd] === undefined) {
handleType[fd] = guessHandleType(fd);
}
return handleType[fd];
}

function formatAndWrite(fd, obj, ignoreErrors, colors = false) {
const str = `${formatWithOptions({ colors }, obj)}\n`;
const ctx = {};
writeString(fd, str, null, undefined, undefined, ctx);
if (!ignoreErrors) {
handleErrorFromBinding(ctx);
}
}

let colors;
function getColors() {
if (colors === undefined) {
colors = require('internal/tty').getColorDepth() > 2;
}
return colors;
}

// TODO(joyeecheung): replace more internal process._rawDebug()
// and console.log() usage with this if possible.
function print(fd, obj, ignoreErrors = true) {
switch (getFdType(fd)) {
case 'TTY':
formatAndWrite(fd, obj, ignoreErrors, getColors());
break;
case 'FILE':
formatAndWrite(fd, obj, ignoreErrors);
break;
case 'PIPE':
case 'TCP':
// Fallback to console.log to handle IPC.
if (process.channel && process.channel.fd === fd) {
log(obj);
} else {
formatAndWrite(fd, obj, ignoreErrors);
}
break;
default:
log(obj);
}
}

module.exports = {
print,
kStderr,
kStdout
};
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
'lib/internal/url.js',
'lib/internal/util.js',
'lib/internal/util/comparisons.js',
'lib/internal/util/print.js',
'lib/internal/util/debuglog.js',
'lib/internal/util/inspect.js',
'lib/internal/util/inspector.js',
Expand Down
10 changes: 7 additions & 3 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,13 @@ MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
->GetFunction(env->context())
.ToLocalChecked()};

MaybeLocal<Value> result =
ExecuteBootstrapper(env, main_script_id, &parameters, &arguments);
return scope.EscapeMaybe(result);
Local<Value> result;
if (!ExecuteBootstrapper(env, main_script_id, &parameters, &arguments)
.ToLocal(&result) ||
!task_queue::RunNextTicksNative(env)) {
return MaybeLocal<Value>();
}
return scope.Escape(result);
}

MaybeLocal<Value> StartMainThreadExecution(Environment* env) {
Expand Down
10 changes: 10 additions & 0 deletions src/node_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ v8::MaybeLocal<v8::Object> CreateProcessObject(
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args);
void PatchProcessObject(const v8::FunctionCallbackInfo<v8::Value>& args);

namespace task_queue {
// Handle any nextTicks added in the first tick of the program.
// We use the native version here for once so that any microtasks
// created by the main module is then handled from C++, and
// the call stack of the main script does not show up in the async error
// stack trace.
bool RunNextTicksNative(Environment* env);
} // namespace task_queue

} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_NODE_PROCESS_H_
15 changes: 15 additions & 0 deletions src/node_task_queue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "node.h"
#include "node_errors.h"
#include "node_internals.h"
#include "node_process.h"
#include "v8.h"

#include <atomic>
Expand Down Expand Up @@ -38,6 +39,20 @@ static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
isolate->EnqueueMicrotask(args[0].As<Function>());
}

// Should be in sync with runNextTicks in internal/process/task_queues.js
bool RunNextTicksNative(Environment* env) {
TickInfo* tick_info = env->tick_info();
if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn())
env->isolate()->RunMicrotasks();
if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn())
return true;

Local<Function> callback = env->tick_callback_function();
CHECK(!callback.IsEmpty());
return !callback->Call(env->context(), env->process_object(), 0, nullptr)
.IsEmpty();
}

static void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
args.GetIsolate()->RunMicrotasks();
}
Expand Down
1 change: 1 addition & 0 deletions test/benchmark/test-benchmark-misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ runBenchmark('misc', [
'method=',
'n=1',
'type=',
'code=1',
'val=magyarország.icom.museum',
'script=test/fixtures/semicolon',
'mode=worker'
Expand Down
Loading

0 comments on commit 8bb3445

Please sign in to comment.