summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBradley Farias <bradley.meck@gmail.com>2017-10-03 10:07:48 -0500
committerBradley Farias <bradley.meck@gmail.com>2017-10-12 09:13:29 -0500
commita36aa049c857d87580548d096743f0acf28d231b (patch)
treea24545ea69d8d1d859893eddd1623ffe67a685d7 /src
parent75d41cf531c19496c854acf65d48d9c8421907bc (diff)
downloadandroid-node-v8-a36aa049c857d87580548d096743f0acf28d231b.tar.gz
android-node-v8-a36aa049c857d87580548d096743f0acf28d231b.tar.bz2
android-node-v8-a36aa049c857d87580548d096743f0acf28d231b.zip
src: add internalBindings for binding isolation
This commit adds a method to internal/process that allows access to bindings that are not intended to be used by user code. It has a separate cache object and modlist in order to avoid collisions. You can use NODE_MODULE_CONTEXT_AWARE_INTERNAL to register a C++ module as an internal. PR-URL: https://github.com/nodejs/node/pull/15759 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net> Reviewed-By: Refael Ackermann <refack@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/env-inl.h12
-rw-r--r--src/env.h1
-rw-r--r--src/module_wrap.cc5
-rw-r--r--src/node.cc134
-rw-r--r--src/node.h8
-rw-r--r--src/node_internals.h3
6 files changed, 117 insertions, 46 deletions
diff --git a/src/env-inl.h b/src/env-inl.h
index 0297e66977..c8f8b21e03 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -303,7 +303,17 @@ inline Environment::Environment(IsolateData* isolate_data,
v8::HandleScope handle_scope(isolate());
v8::Context::Scope context_scope(context);
set_as_external(v8::External::New(isolate(), this));
- set_binding_cache_object(v8::Object::New(isolate()));
+
+ v8::Local<v8::Primitive> null = v8::Null(isolate());
+ v8::Local<v8::Object> binding_cache_object = v8::Object::New(isolate());
+ CHECK(binding_cache_object->SetPrototype(context, null).FromJust());
+ set_binding_cache_object(binding_cache_object);
+
+ v8::Local<v8::Object> internal_binding_cache_object =
+ v8::Object::New(isolate());
+ CHECK(internal_binding_cache_object->SetPrototype(context, null).FromJust());
+ set_internal_binding_cache_object(internal_binding_cache_object);
+
set_module_load_list_array(v8::Array::New(isolate()));
AssignToContext(context);
diff --git a/src/env.h b/src/env.h
index 567d87a313..18f1de17cc 100644
--- a/src/env.h
+++ b/src/env.h
@@ -302,6 +302,7 @@ class ModuleWrap;
V(async_hooks_after_function, v8::Function) \
V(async_hooks_promise_resolve_function, v8::Function) \
V(binding_cache_object, v8::Object) \
+ V(internal_binding_cache_object, v8::Object) \
V(buffer_prototype_object, v8::Object) \
V(context, v8::Context) \
V(domain_array, v8::Array) \
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
index cbee6faff3..829248b681 100644
--- a/src/module_wrap.cc
+++ b/src/module_wrap.cc
@@ -7,6 +7,7 @@
#include "node_url.h"
#include "util.h"
#include "util-inl.h"
+#include "node_internals.h"
namespace node {
namespace loader {
@@ -523,5 +524,5 @@ void ModuleWrap::Initialize(Local<Object> target,
} // namespace loader
} // namespace node
-NODE_MODULE_CONTEXT_AWARE_BUILTIN(module_wrap,
- node::loader::ModuleWrap::Initialize)
+NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap,
+ node::loader::ModuleWrap::Initialize)
diff --git a/src/node.cc b/src/node.cc
index a73d8b5807..1bc75abef3 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -183,6 +183,7 @@ static bool v8_is_profiling = false;
static bool node_is_initialized = false;
static node_module* modpending;
static node_module* modlist_builtin;
+static node_module* modlist_internal;
static node_module* modlist_linked;
static node_module* modlist_addon;
static bool trace_enabled = false;
@@ -2574,6 +2575,9 @@ extern "C" void node_module_register(void* m) {
if (mp->nm_flags & NM_F_BUILTIN) {
mp->nm_link = modlist_builtin;
modlist_builtin = mp;
+ } else if (mp->nm_flags & NM_F_INTERNAL) {
+ mp->nm_link = modlist_internal;
+ modlist_internal = mp;
} else if (!node_is_initialized) {
// "Linked" modules are included as part of the node project.
// Like builtins they are registered *before* node::Init runs.
@@ -2585,28 +2589,28 @@ extern "C" void node_module_register(void* m) {
}
}
-struct node_module* get_builtin_module(const char* name) {
+inline struct node_module* FindModule(struct node_module* list,
+ const char* name,
+ int flag) {
struct node_module* mp;
- for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
+ for (mp = list; mp != nullptr; mp = mp->nm_link) {
if (strcmp(mp->nm_modname, name) == 0)
break;
}
- CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
- return (mp);
+ CHECK(mp == nullptr || (mp->nm_flags & flag) != 0);
+ return mp;
}
-struct node_module* get_linked_module(const char* name) {
- struct node_module* mp;
-
- for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
- if (strcmp(mp->nm_modname, name) == 0)
- break;
- }
-
- CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
- return mp;
+node_module* get_builtin_module(const char* name) {
+ return FindModule(modlist_builtin, name, NM_F_BUILTIN);
+}
+node_module* get_internal_module(const char* name) {
+ return FindModule(modlist_internal, name, NM_F_INTERNAL);
+}
+node_module* get_linked_module(const char* name) {
+ return FindModule(modlist_linked, name, NM_F_LINKED);
}
struct DLib {
@@ -2880,24 +2884,60 @@ void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
f.As<v8::Function>()->Call(process, 1, &arg);
}
+static bool PullFromCache(Environment* env,
+ const FunctionCallbackInfo<Value>& args,
+ Local<String> module,
+ Local<Object> cache) {
+ Local<Context> context = env->context();
+ Local<Value> exports_v;
+ Local<Object> exports;
+ if (cache->Get(context, module).ToLocal(&exports_v) &&
+ exports_v->IsObject() &&
+ exports_v->ToObject(context).ToLocal(&exports)) {
+ args.GetReturnValue().Set(exports);
+ return true;
+ }
+ return false;
+}
+
+static Local<Object> InitModule(Environment* env,
+ node_module* mod,
+ Local<String> module) {
+ Local<Object> exports = Object::New(env->isolate());
+ // Internal bindings don't have a "module" object, only exports.
+ CHECK_EQ(mod->nm_register_func, nullptr);
+ CHECK_NE(mod->nm_context_register_func, nullptr);
+ Local<Value> unused = Undefined(env->isolate());
+ mod->nm_context_register_func(exports,
+ unused,
+ env->context(),
+ mod->nm_priv);
+ return exports;
+}
+
+static void ThrowIfNoSuchModule(Environment* env, const char* module_v) {
+ char errmsg[1024];
+ snprintf(errmsg,
+ sizeof(errmsg),
+ "No such module: %s",
+ module_v);
+ env->ThrowError(errmsg);
+}
static void Binding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
- Local<String> module = args[0]->ToString(env->isolate());
- node::Utf8Value module_v(env->isolate(), module);
+ Local<String> module;
+ if (!args[0]->ToString(env->context()).ToLocal(&module)) return;
Local<Object> cache = env->binding_cache_object();
- Local<Object> exports;
- if (cache->Has(env->context(), module).FromJust()) {
- exports = cache->Get(module)->ToObject(env->isolate());
- args.GetReturnValue().Set(exports);
+ if (PullFromCache(env, args, module, cache))
return;
- }
// Append a string to process.moduleLoadList
char buf[1024];
+ node::Utf8Value module_v(env->isolate(), module);
snprintf(buf, sizeof(buf), "Binding %s", *module_v);
Local<Array> modules = env->module_load_list_array();
@@ -2905,33 +2945,49 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
modules->Set(l, OneByteString(env->isolate(), buf));
node_module* mod = get_builtin_module(*module_v);
+ Local<Object> exports;
if (mod != nullptr) {
- exports = Object::New(env->isolate());
- // Internal bindings don't have a "module" object, only exports.
- CHECK_EQ(mod->nm_register_func, nullptr);
- CHECK_NE(mod->nm_context_register_func, nullptr);
- Local<Value> unused = Undefined(env->isolate());
- mod->nm_context_register_func(exports, unused,
- env->context(), mod->nm_priv);
- cache->Set(module, exports);
+ exports = InitModule(env, mod, module);
} else if (!strcmp(*module_v, "constants")) {
exports = Object::New(env->isolate());
CHECK(exports->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
DefineConstants(env->isolate(), exports);
- cache->Set(module, exports);
} else if (!strcmp(*module_v, "natives")) {
exports = Object::New(env->isolate());
DefineJavaScript(env, exports);
- cache->Set(module, exports);
} else {
- char errmsg[1024];
- snprintf(errmsg,
- sizeof(errmsg),
- "No such module: %s",
- *module_v);
- return env->ThrowError(errmsg);
+ return ThrowIfNoSuchModule(env, *module_v);
}
+ cache->Set(module, exports);
+
+ args.GetReturnValue().Set(exports);
+}
+
+static void InternalBinding(const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args);
+
+ Local<String> module;
+ if (!args[0]->ToString(env->context()).ToLocal(&module)) return;
+
+ Local<Object> cache = env->internal_binding_cache_object();
+
+ if (PullFromCache(env, args, module, cache))
+ return;
+
+ // Append a string to process.moduleLoadList
+ char buf[1024];
+ node::Utf8Value module_v(env->isolate(), module);
+ snprintf(buf, sizeof(buf), "Internal Binding %s", *module_v);
+
+ Local<Array> modules = env->module_load_list_array();
+ uint32_t l = modules->Length();
+ modules->Set(l, OneByteString(env->isolate(), buf));
+
+ node_module* mod = get_internal_module(*module_v);
+ if (mod == nullptr) return ThrowIfNoSuchModule(env, *module_v);
+ Local<Object> exports = InitModule(env, mod, module);
+ cache->Set(module, exports);
args.GetReturnValue().Set(exports);
}
@@ -2939,7 +2995,8 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args.GetIsolate());
- Local<String> module_name = args[0]->ToString(env->isolate());
+ Local<String> module_name;
+ if (!args[0]->ToString(env->context()).ToLocal(&module_name)) return;
Local<Object> cache = env->binding_cache_object();
Local<Value> exports_v = cache->Get(module_name);
@@ -3674,6 +3731,7 @@ void SetupProcessObject(Environment* env,
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);
diff --git a/src/node.h b/src/node.h
index 287823b17b..aa8738a567 100644
--- a/src/node.h
+++ b/src/node.h
@@ -421,8 +421,9 @@ typedef void (*addon_context_register_func)(
v8::Local<v8::Context> context,
void* priv);
-#define NM_F_BUILTIN 0x01
-#define NM_F_LINKED 0x02
+#define NM_F_BUILTIN 0x01
+#define NM_F_LINKED 0x02
+#define NM_F_INTERNAL 0x04
struct node_module {
int nm_version;
@@ -436,9 +437,6 @@ struct node_module {
struct node_module* nm_link;
};
-node_module* get_builtin_module(const char *name);
-node_module* get_linked_module(const char *name);
-
extern "C" NODE_EXTERN void node_module_register(void* mod);
#ifdef _WIN32
diff --git a/src/node_internals.h b/src/node_internals.h
index 7c4f7a6a7f..54f20c39d3 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -324,6 +324,9 @@ class InternalCallbackScope {
bool closed_ = false;
};
+#define NODE_MODULE_CONTEXT_AWARE_INTERNAL(modname, regfunc) \
+ NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, NM_F_INTERNAL) \
+
} // namespace node