diff options
author | Bradley Farias <bradley.meck@gmail.com> | 2017-10-03 10:07:48 -0500 |
---|---|---|
committer | Bradley Farias <bradley.meck@gmail.com> | 2017-10-12 09:13:29 -0500 |
commit | a36aa049c857d87580548d096743f0acf28d231b (patch) | |
tree | a24545ea69d8d1d859893eddd1623ffe67a685d7 /src | |
parent | 75d41cf531c19496c854acf65d48d9c8421907bc (diff) | |
download | android-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.h | 12 | ||||
-rw-r--r-- | src/env.h | 1 | ||||
-rw-r--r-- | src/module_wrap.cc | 5 | ||||
-rw-r--r-- | src/node.cc | 134 | ||||
-rw-r--r-- | src/node.h | 8 | ||||
-rw-r--r-- | src/node_internals.h | 3 |
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); @@ -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 |