src: move internal loaders out of bootstrap_node.js

- Moves the creation of `process.binding()`, `process._linkedBinding()`
  `internalBinding()` and `NativeModule` into a separate file
  `lib/internal/bootstrap_loaders.js`, and documents them there.
  This file will be compiled and run before `bootstrap_node.js`, which
  means we now bootstrap the internal module & binding system before
  actually bootstrapping Node.js.
- Rename the special ID that can be used to require `NativeModule`
  as `internal/bootstrap_loaders` since it is setup there. Also put
  `internalBinding` in the object exported by `NativeModule.require`
  instead of putting it inside the `NativeModule.wrapper`
- Use the original `getBinding()` to get the source code of native
  modules instead of getting it from `process.binding('native')`
  so that users cannot fake native modules by modifying the binding
  object.
- Names the bootstrapping functions so their names show up
  in the stack trace.

PR-URL: https://github.com/nodejs/node/pull/19112
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
This commit is contained in:
Joyee Cheung 2018-03-04 04:55:45 +08:00
Родитель 1a5ec837ca
Коммит 2a9eb316a1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F586868AAD831D0C
29 изменённых файлов: 391 добавлений и 233 удалений

Просмотреть файл

@ -244,7 +244,6 @@ module.exports = {
DTRACE_HTTP_SERVER_REQUEST: false,
DTRACE_HTTP_SERVER_RESPONSE: false,
DTRACE_NET_SERVER_CONNECTION: false,
DTRACE_NET_STREAM_END: false,
internalBinding: false,
DTRACE_NET_STREAM_END: false
},
};

Просмотреть файл

@ -36,7 +36,7 @@ const { openSync, closeSync, readSync } = require('fs');
const { parseExpressionAt } = require('internal/deps/acorn/dist/acorn');
const { inspect } = require('util');
const { EOL } = require('os');
const nativeModule = require('native_module');
const { NativeModule } = require('internal/bootstrap_loaders');
// Escape control characters but not \n and \t to keep the line breaks and
// indentation intact.
@ -163,7 +163,7 @@ function getErrMessage(call) {
}
// Skip Node.js modules!
if (filename.endsWith('.js') && nativeModule.exists(filename.slice(0, -3))) {
if (filename.endsWith('.js') && NativeModule.exists(filename.slice(0, -3))) {
errorCache.set(identifier, undefined);
return;
}

Просмотреть файл

@ -41,6 +41,7 @@ const {
// that test/parallel/test-buffer-bindingobj-no-zerofill.js is written.
let isAnyArrayBuffer;
try {
const { internalBinding } = require('internal/bootstrap_loaders');
isAnyArrayBuffer = internalBinding('types').isAnyArrayBuffer;
} catch (e) {
isAnyArrayBuffer = require('util').types.isAnyArrayBuffer;

Просмотреть файл

@ -34,6 +34,7 @@ const {
ERR_UNHANDLED_ERROR
} = require('internal/errors').codes;
const { createHook } = require('async_hooks');
const { internalBinding } = require('internal/bootstrap_loaders');
// overwrite process.domain with a getter/setter that will allow for more
// effective optimizations

229
lib/internal/bootstrap_loaders.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,229 @@
// This file creates the internal module & binding loaders used by built-in
// modules. In contrast, user land modules are loaded using
// lib/module.js (CommonJS Modules) or lib/internal/loader/* (ES Modules).
//
// This file is compiled and run by node.cc before bootstrap_node.js
// was called, therefore the loaders are bootstraped before we start to
// actually bootstrap Node.js. It creates the following objects:
//
// C++ binding loaders:
// - process.binding(): the legacy C++ binding loader, accessible from user land
// because it is an object attached to the global process object.
// These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE()
// and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees
// about the stability of these bindings, but still have to take care of
// compatibility issues caused by them from time to time.
// - process._linkedBinding(): intended to be used by embedders to add
// additional C++ bindings in their applications. These C++ bindings
// can be created using NODE_MODULE_CONTEXT_AWARE_CPP() with the flag
// NM_F_LINKED.
// - internalBinding(): the private internal C++ binding loader, inaccessible
// from user land because they are only available from NativeModule.require()
// These C++ bindings are created using NODE_MODULE_CONTEXT_AWARE_INTERNAL()
// and have their nm_flags set to NM_F_INTERNAL.
//
// Internal JavaScript module loader:
// - NativeModule: a minimal module system used to load the JavaScript core
// modules found in lib/**/*.js and deps/**/*.js. All core modules are
// compiled into the node binary via node_javascript.cc generated by js2c.py,
// so they can be loaded faster without the cost of I/O. This class makes the
// lib/internal/*, deps/internal/* modules and internalBinding() available by
// default to core modules, and lets the core modules require itself via
// require('internal/bootstrap_loaders') even when this file is not written in
// CommonJS style.
//
// Other objects:
// - process.moduleLoadList: an array recording the bindings and the modules
// loaded in the process and the order in which they are loaded.
'use strict';
(function bootstrapInternalLoaders(process, getBinding, getLinkedBinding,
getInternalBinding) {
// Set up process.moduleLoadList
const moduleLoadList = [];
Object.defineProperty(process, 'moduleLoadList', {
value: moduleLoadList,
configurable: true,
enumerable: true,
writable: false
});
// Set up process.binding() and process._linkedBinding()
{
const bindingObj = Object.create(null);
process.binding = function binding(module) {
module = String(module);
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getBinding(module);
moduleLoadList.push(`Binding ${module}`);
}
return mod;
};
process._linkedBinding = function _linkedBinding(module) {
module = String(module);
let mod = bindingObj[module];
if (typeof mod !== 'object')
mod = bindingObj[module] = getLinkedBinding(module);
return mod;
};
}
// Set up internalBinding() in the closure
let internalBinding;
{
const bindingObj = Object.create(null);
internalBinding = function internalBinding(module) {
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getInternalBinding(module);
moduleLoadList.push(`Internal Binding ${module}`);
}
return mod;
};
}
// Minimal sandbox helper
const ContextifyScript = process.binding('contextify').ContextifyScript;
function runInThisContext(code, options) {
const script = new ContextifyScript(code, options);
return script.runInThisContext();
}
// Set up NativeModule
function NativeModule(id) {
this.filename = `${id}.js`;
this.id = id;
this.exports = {};
this.loaded = false;
this.loading = false;
}
NativeModule._source = getBinding('natives');
NativeModule._cache = {};
const config = getBinding('config');
// Think of this as module.exports in this file even though it is not
// written in CommonJS style.
const loaderExports = { internalBinding, NativeModule };
const loaderId = 'internal/bootstrap_loaders';
NativeModule.require = function(id) {
if (id === loaderId) {
return loaderExports;
}
const cached = NativeModule.getCached(id);
if (cached && (cached.loaded || cached.loading)) {
return cached.exports;
}
if (!NativeModule.exists(id)) {
// Model the error off the internal/errors.js model, but
// do not use that module given that it could actually be
// the one causing the error if there's a bug in Node.js
const err = new Error(`No such built-in module: ${id}`);
err.code = 'ERR_UNKNOWN_BUILTIN_MODULE';
err.name = 'Error [ERR_UNKNOWN_BUILTIN_MODULE]';
throw err;
}
moduleLoadList.push(`NativeModule ${id}`);
const nativeModule = new NativeModule(id);
nativeModule.cache();
nativeModule.compile();
return nativeModule.exports;
};
NativeModule.requireForDeps = function(id) {
if (!NativeModule.exists(id) ||
// TODO(TimothyGu): remove when DEP0084 reaches end of life.
id.startsWith('node-inspect/') ||
id.startsWith('v8/')) {
id = `internal/deps/${id}`;
}
return NativeModule.require(id);
};
NativeModule.getCached = function(id) {
return NativeModule._cache[id];
};
NativeModule.exists = function(id) {
return NativeModule._source.hasOwnProperty(id);
};
if (config.exposeInternals) {
NativeModule.nonInternalExists = function(id) {
// Do not expose this to user land even with --expose-internals
if (id === loaderId) {
return false;
}
return NativeModule.exists(id);
};
NativeModule.isInternal = function(id) {
// Do not expose this to user land even with --expose-internals
return id === loaderId;
};
} else {
NativeModule.nonInternalExists = function(id) {
return NativeModule.exists(id) && !NativeModule.isInternal(id);
};
NativeModule.isInternal = function(id) {
return id.startsWith('internal/');
};
}
NativeModule.getSource = function(id) {
return NativeModule._source[id];
};
NativeModule.wrap = function(script) {
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};
NativeModule.wrapper = [
'(function (exports, require, module, process) {',
'\n});'
];
NativeModule.prototype.compile = function() {
let source = NativeModule.getSource(this.id);
source = NativeModule.wrap(source);
this.loading = true;
try {
const fn = runInThisContext(source, {
filename: this.filename,
lineOffset: 0,
displayErrors: true
});
const requireFn = this.id.startsWith('internal/deps/') ?
NativeModule.requireForDeps :
NativeModule.require;
fn(this.exports, requireFn, this, process);
this.loaded = true;
} finally {
this.loading = false;
}
};
NativeModule.prototype.cache = function() {
NativeModule._cache[this.id] = this;
};
// This will be passed to the bootstrapNodeJSCore function in
// bootstrap_node.js.
return loaderExports;
});

185
lib/internal/bootstrap_node.js поставляемый
Просмотреть файл

@ -4,11 +4,16 @@
// responsible for bootstrapping the node.js core. As special caution is given
// to the performance of the startup process, many dependencies are invoked
// lazily.
//
// Before this file is run, lib/internal/bootstrap_loaders.js gets run first
// to bootstrap the internal binding and module loaders, including
// process.binding(), process._linkedBinding(), internalBinding() and
// NativeModule. And then { internalBinding, NativeModule } will be passed
// into this bootstrapper to bootstrap Node.js core.
'use strict';
(function(process) {
let internalBinding;
(function bootstrapNodeJSCore(process, { internalBinding, NativeModule }) {
const exceptionHandlerState = { captureFn: null };
function startup() {
@ -270,54 +275,6 @@
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
}
const moduleLoadList = [];
Object.defineProperty(process, 'moduleLoadList', {
value: moduleLoadList,
configurable: true,
enumerable: true,
writable: false
});
{
const bindingObj = Object.create(null);
const getBinding = process.binding;
process.binding = function binding(module) {
module = String(module);
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getBinding(module);
moduleLoadList.push(`Binding ${module}`);
}
return mod;
};
const getLinkedBinding = process._linkedBinding;
process._linkedBinding = function _linkedBinding(module) {
module = String(module);
let mod = bindingObj[module];
if (typeof mod !== 'object')
mod = bindingObj[module] = getLinkedBinding(module);
return mod;
};
}
{
const bindingObj = Object.create(null);
const getInternalBinding = process._internalBinding;
delete process._internalBinding;
internalBinding = function internalBinding(module) {
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getInternalBinding(module);
moduleLoadList.push(`Internal Binding ${module}`);
}
return mod;
};
}
function setupProcessObject() {
process._setupProcessObject(pushValueToArray);
@ -602,133 +559,5 @@
new vm.Script(source, { displayErrors: true, filename });
}
// Below you find a minimal module system, which is used to load the node
// core modules found in lib/*.js. All core modules are compiled into the
// node binary, so they can be loaded faster.
const ContextifyScript = process.binding('contextify').ContextifyScript;
function runInThisContext(code, options) {
const script = new ContextifyScript(code, options);
return script.runInThisContext();
}
function NativeModule(id) {
this.filename = `${id}.js`;
this.id = id;
this.exports = {};
this.loaded = false;
this.loading = false;
}
NativeModule._source = process.binding('natives');
NativeModule._cache = {};
const config = process.binding('config');
NativeModule.require = function(id) {
if (id === 'native_module') {
return NativeModule;
}
const cached = NativeModule.getCached(id);
if (cached && (cached.loaded || cached.loading)) {
return cached.exports;
}
if (!NativeModule.exists(id)) {
// Model the error off the internal/errors.js model, but
// do not use that module given that it could actually be
// the one causing the error if there's a bug in Node.js
const err = new Error(`No such built-in module: ${id}`);
err.code = 'ERR_UNKNOWN_BUILTIN_MODULE';
err.name = 'Error [ERR_UNKNOWN_BUILTIN_MODULE]';
throw err;
}
moduleLoadList.push(`NativeModule ${id}`);
const nativeModule = new NativeModule(id);
nativeModule.cache();
nativeModule.compile();
return nativeModule.exports;
};
NativeModule.requireForDeps = function(id) {
if (!NativeModule.exists(id) ||
// TODO(TimothyGu): remove when DEP0084 reaches end of life.
id.startsWith('node-inspect/') ||
id.startsWith('v8/')) {
id = `internal/deps/${id}`;
}
return NativeModule.require(id);
};
NativeModule.getCached = function(id) {
return NativeModule._cache[id];
};
NativeModule.exists = function(id) {
return NativeModule._source.hasOwnProperty(id);
};
if (config.exposeInternals) {
NativeModule.nonInternalExists = NativeModule.exists;
NativeModule.isInternal = function(id) {
return false;
};
} else {
NativeModule.nonInternalExists = function(id) {
return NativeModule.exists(id) && !NativeModule.isInternal(id);
};
NativeModule.isInternal = function(id) {
return id.startsWith('internal/');
};
}
NativeModule.getSource = function(id) {
return NativeModule._source[id];
};
NativeModule.wrap = function(script) {
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};
NativeModule.wrapper = [
'(function (exports, require, module, internalBinding, process) {',
'\n});'
];
NativeModule.prototype.compile = function() {
let source = NativeModule.getSource(this.id);
source = NativeModule.wrap(source);
this.loading = true;
try {
const fn = runInThisContext(source, {
filename: this.filename,
lineOffset: 0,
displayErrors: true
});
const requireFn = this.id.startsWith('internal/deps/') ?
NativeModule.requireForDeps :
NativeModule.require;
fn(this.exports, requireFn, this, internalBinding, process);
this.loaded = true;
} finally {
this.loading = false;
}
};
NativeModule.prototype.cache = function() {
NativeModule._cache[this.id] = this;
};
startup();
});

Просмотреть файл

@ -17,6 +17,7 @@ const {
const { isArrayBufferView } = require('internal/util/types');
const { internalBinding } = require('internal/bootstrap_loaders');
const {
isArrayBuffer
} = internalBinding('types');

Просмотреть файл

@ -1,5 +1,6 @@
'use strict';
const { internalBinding } = require('internal/bootstrap_loaders');
const { ModuleWrap } = internalBinding('module_wrap');
const debug = require('util').debuglog('esm');
const ArrayJoin = Function.call.bind(Array.prototype.join);

Просмотреть файл

@ -3,7 +3,7 @@
const { URL } = require('url');
const CJSmodule = require('module');
const internalFS = require('internal/fs');
const NativeModule = require('native_module');
const { NativeModule, internalBinding } = require('internal/bootstrap_loaders');
const { extname } = require('path');
const { realpathSync } = require('fs');
const preserveSymlinks = !!process.binding('config').preserveSymlinks;

Просмотреть файл

@ -1,5 +1,6 @@
'use strict';
const { internalBinding } = require('internal/bootstrap_loaders');
const { ModuleWrap } = internalBinding('module_wrap');
const { SafeSet, SafePromise } = require('internal/safe_globals');
const { decorateErrorStack } = require('internal/util');

Просмотреть файл

@ -1,7 +1,7 @@
'use strict';
const { NativeModule, internalBinding } = require('internal/bootstrap_loaders');
const { ModuleWrap } = internalBinding('module_wrap');
const NativeModule = require('native_module');
const internalCJSModule = require('internal/module');
const CJSModule = require('module');
const internalURLModule = require('internal/url');

Просмотреть файл

@ -1,5 +1,6 @@
'use strict';
const { internalBinding } = require('internal/bootstrap_loaders');
const {
setImportModuleDynamicallyCallback,
setInitializeImportMetaObjectCallback

Просмотреть файл

@ -8,6 +8,7 @@ process.emitWarning(
// These exports should be scoped as specifically as possible
// to avoid exposing APIs because even with that warning and
// this file being internal people will still try to abuse it.
const { internalBinding } = require('internal/bootstrap_loaders');
module.exports = {
ModuleWrap: internalBinding('module_wrap').ModuleWrap,
};

Просмотреть файл

@ -2,6 +2,7 @@
const { compare } = process.binding('buffer');
const { isArrayBufferView } = require('internal/util/types');
const { internalBinding } = require('internal/bootstrap_loaders');
const { isDate, isMap, isRegExp, isSet } = internalBinding('types');
function objectToString(o) {

Просмотреть файл

@ -1,5 +1,6 @@
'use strict';
const { internalBinding } = require('internal/bootstrap_loaders');
const { emitExperimentalWarning } = require('internal/util');
const { URL } = require('internal/url');
const { kParsingContext, isContext } = process.binding('contextify');

Просмотреть файл

@ -21,7 +21,7 @@
'use strict';
const NativeModule = require('native_module');
const { NativeModule } = require('internal/bootstrap_loaders');
const util = require('util');
const { decorateErrorStack } = require('internal/util');
const { getURLFromFilePath } = require('internal/url');

Просмотреть файл

@ -22,6 +22,7 @@
'use strict';
const { Buffer } = require('buffer');
const { internalBinding } = require('internal/bootstrap_loaders');
const {
kIncompleteCharactersStart,
kIncompleteCharactersEnd,

Просмотреть файл

@ -39,6 +39,7 @@ const {
kRejected,
} = process.binding('util');
const { internalBinding } = require('internal/bootstrap_loaders');
const types = internalBinding('types');
Object.assign(types, require('internal/util/types'));
const {

Просмотреть файл

@ -24,6 +24,7 @@
'node_lib_target_name%': 'node_lib',
'node_intermediate_lib_type%': 'static_library',
'library_files': [
'lib/internal/bootstrap_loaders.js',
'lib/internal/bootstrap_node.js',
'lib/async_hooks.js',
'lib/assert.js',

Просмотреть файл

@ -2525,7 +2525,7 @@ static void ThrowIfNoSuchModule(Environment* env, const char* module_v) {
env->ThrowError(errmsg);
}
static void Binding(const FunctionCallbackInfo<Value>& args) {
static void GetBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsString());
@ -2552,7 +2552,7 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(exports);
}
static void InternalBinding(const FunctionCallbackInfo<Value>& args) {
static void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsString());
@ -2567,7 +2567,7 @@ static void InternalBinding(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(exports);
}
static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
static void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args.GetIsolate());
CHECK(args[0]->IsString());
@ -3265,10 +3265,6 @@ void SetupProcessObject(Environment* env,
env->SetMethod(process, "uptime", Uptime);
env->SetMethod(process, "memoryUsage", MemoryUsage);
env->SetMethod(process, "binding", Binding);
env->SetMethod(process, "_linkedBinding", LinkedBinding);
env->SetMethod(process, "_internalBinding", InternalBinding);
env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
env->SetMethod(process, "_setupNextTick", SetupNextTick);
env->SetMethod(process, "_setupPromises", SetupPromises);
@ -3306,8 +3302,10 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
fflush(stderr);
}
void LoadEnvironment(Environment* env) {
HandleScope handle_scope(env->isolate());
static Local<Function> GetBootstrapper(Environment* env, Local<String> source,
Local<String> script_name) {
EscapableHandleScope scope(env->isolate());
TryCatch try_catch(env->isolate());
@ -3316,20 +3314,59 @@ void LoadEnvironment(Environment* env) {
// are not safe to ignore.
try_catch.SetVerbose(false);
// Execute the lib/internal/bootstrap_node.js file which was included as a
// static C string in node_natives.h by node_js2c.
// 'internal_bootstrap_node_native' is the string containing that source code.
Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
"bootstrap_node.js");
Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
// Execute the factory javascript file
Local<Value> factory_v = ExecuteString(env, source, script_name);
if (try_catch.HasCaught()) {
ReportException(env, try_catch);
exit(10);
}
// The bootstrap_node.js file returns a function 'f'
CHECK(f_value->IsFunction());
Local<Function> f = Local<Function>::Cast(f_value);
CHECK(factory_v->IsFunction());
Local<Function> factory = Local<Function>::Cast(factory_v);
return scope.Escape(factory);
}
static bool ExecuteBootstrapper(Environment* env, Local<Function> factory,
int argc, Local<Value> argv[],
Local<Value>* out) {
bool ret = factory->Call(
env->context(), Null(env->isolate()), argc, argv).ToLocal(out);
// If there was an error during bootstrap then it was either handled by the
// FatalException handler or it's unrecoverable (e.g. max call stack
// exceeded). Either way, clear the stack so that the AsyncCallbackScope
// destructor doesn't fail on the id check.
// There are only two ways to have a stack size > 1: 1) the user manually
// called MakeCallback or 2) user awaited during bootstrap, which triggered
// _tickCallback().
if (!ret) {
env->async_hooks()->clear_async_id_stack();
}
return ret;
}
void LoadEnvironment(Environment* env) {
HandleScope handle_scope(env->isolate());
TryCatch try_catch(env->isolate());
// Disable verbose mode to stop FatalException() handler from trying
// to handle the exception. Errors this early in the start-up phase
// are not safe to ignore.
try_catch.SetVerbose(false);
// The factory scripts are lib/internal/bootstrap_loaders.js and
// lib/internal/bootstrap_node.js, each included as a static C string
// defined in node_javascript.h, generated in node_javascript.cc by
// node_js2c.
Local<Function> loaders_bootstrapper =
GetBootstrapper(env, LoadersBootstrapperSource(env),
FIXED_ONE_BYTE_STRING(env->isolate(), "bootstrap_loaders.js"));
Local<Function> node_bootstrapper =
GetBootstrapper(env, NodeBootstrapperSource(env),
FIXED_ONE_BYTE_STRING(env->isolate(), "bootstrap_node.js"));
// Add a reference to the global object
Local<Object> global = env->context()->Global();
@ -3356,25 +3393,47 @@ void LoadEnvironment(Environment* env) {
// (Allows you to set stuff on `global` from anywhere in JavaScript.)
global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
// Now we call 'f' with the 'process' variable that we've built up with
// all our bindings. Inside bootstrap_node.js and internal/process we'll
// take care of assigning things to their places.
// Create binding loaders
v8::Local<v8::Function> get_binding_fn =
env->NewFunctionTemplate(GetBinding)->GetFunction(env->context())
.ToLocalChecked();
// We start the process this way in order to be more modular. Developers
// who do not like how bootstrap_node.js sets up the module system but do
// like Node's I/O bindings may want to replace 'f' with their own function.
Local<Value> arg = env->process_object();
v8::Local<v8::Function> get_linked_binding_fn =
env->NewFunctionTemplate(GetLinkedBinding)->GetFunction(env->context())
.ToLocalChecked();
auto ret = f->Call(env->context(), Null(env->isolate()), 1, &arg);
// If there was an error during bootstrap then it was either handled by the
// FatalException handler or it's unrecoverable (e.g. max call stack
// exceeded). Either way, clear the stack so that the AsyncCallbackScope
// destructor doesn't fail on the id check.
// There are only two ways to have a stack size > 1: 1) the user manually
// called MakeCallback or 2) user awaited during bootstrap, which triggered
// _tickCallback().
if (ret.IsEmpty())
env->async_hooks()->clear_async_id_stack();
v8::Local<v8::Function> get_internal_binding_fn =
env->NewFunctionTemplate(GetInternalBinding)->GetFunction(env->context())
.ToLocalChecked();
Local<Value> loaders_bootstrapper_args[] = {
env->process_object(),
get_binding_fn,
get_linked_binding_fn,
get_internal_binding_fn
};
// Bootstrap internal loaders
Local<Value> bootstrapped_loaders;
if (!ExecuteBootstrapper(env, loaders_bootstrapper,
arraysize(loaders_bootstrapper_args),
loaders_bootstrapper_args,
&bootstrapped_loaders)) {
return;
}
// Bootstrap Node.js
Local<Value> bootstrapped_node;
Local<Value> node_bootstrapper_args[] = {
env->process_object(),
bootstrapped_loaders
};
if (!ExecuteBootstrapper(env, node_bootstrapper,
arraysize(node_bootstrapper_args),
node_bootstrapper_args,
&bootstrapped_node)) {
return;
}
}
static void PrintHelp() {

Просмотреть файл

@ -29,7 +29,8 @@
namespace node {
void DefineJavaScript(Environment* env, v8::Local<v8::Object> target);
v8::Local<v8::String> MainSource(Environment* env);
v8::Local<v8::String> LoadersBootstrapperSource(Environment* env);
v8::Local<v8::String> NodeBootstrapperSource(Environment* env);
} // namespace node

Просмотреть файл

@ -12,4 +12,4 @@ AssertionError [ERR_ASSERTION]: 1 strictEqual 2
at Function.Module._load (module.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)

Просмотреть файл

@ -10,7 +10,7 @@ SyntaxError: Strict mode code may not include a with statement
at Module._compile (module.js:*:*)
at evalScript (bootstrap_node.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
42
42
[eval]:1
@ -25,7 +25,7 @@ Error: hello
at Module._compile (module.js:*:*)
at evalScript (bootstrap_node.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
[eval]:1
throw new Error("hello")
@ -39,7 +39,7 @@ Error: hello
at Module._compile (module.js:*:*)
at evalScript (bootstrap_node.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
100
[eval]:1
var x = 100; y = x;
@ -53,7 +53,7 @@ ReferenceError: y is not defined
at Module._compile (module.js:*:*)
at evalScript (bootstrap_node.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
[eval]:1
var ______________________________________________; throw 10

Просмотреть файл

@ -19,4 +19,4 @@ Emitted 'error' event at:
at Module._compile (module.js:*:*)
[... lines matching original stack trace ...]
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)

Просмотреть файл

@ -11,10 +11,10 @@ Error
at Function.Module._load (module.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
Emitted 'error' event at:
at process.nextTick (*events_unhandled_error_nexttick.js:*:*)
at process._tickCallback (internal/process/next_tick.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)

Просмотреть файл

@ -11,9 +11,9 @@ Error
at Function.Module._load (module.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)
Emitted 'error' event at:
at Object.<anonymous> (*events_unhandled_error_sameline.js:*:*)
at Module._compile (module.js:*:*)
[... lines matching original stack trace ...]
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)

Просмотреть файл

@ -7,4 +7,4 @@ ReferenceError: undefined_reference_error_maker is not defined
at process._tickCallback (internal/process/next_tick.js:*:*)
at Function.Module.runMain (module.js:*:*)
at startup (bootstrap_node.js:*:*)
at bootstrap_node.js:*:*
at bootstrapNodeJSCore (bootstrap_node.js:*:*)

Просмотреть файл

@ -0,0 +1,25 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');
common.expectsError(
() => {
require('internal/bootstrap_loaders');
}, {
code: 'MODULE_NOT_FOUND',
message: 'Cannot find module \'internal/bootstrap_loaders\''
}
);
common.expectsError(
() => {
const source = 'module.exports = require("internal/bootstrap_loaders")';
process.binding('natives').owo = source;
require('owo');
}, {
code: 'MODULE_NOT_FOUND',
message: 'Cannot find module \'owo\''
}
);

Просмотреть файл

@ -185,7 +185,11 @@ namespace node {{
{definitions}
v8::Local<v8::String> MainSource(Environment* env) {{
v8::Local<v8::String> LoadersBootstrapperSource(Environment* env) {{
return internal_bootstrap_loaders_value.ToStringChecked(env->isolate());
}}
v8::Local<v8::String> NodeBootstrapperSource(Environment* env) {{
return internal_bootstrap_node_value.ToStringChecked(env->isolate());
}}