aboutsummaryrefslogtreecommitdiff
path: root/src/node_native_module.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/node_native_module.cc')
-rw-r--r--src/node_native_module.cc319
1 files changed, 73 insertions, 246 deletions
diff --git a/src/node_native_module.cc b/src/node_native_module.cc
index 6462f39ee1..814adb620d 100644
--- a/src/node_native_module.cc
+++ b/src/node_native_module.cc
@@ -1,40 +1,60 @@
#include "node_native_module.h"
-#include "node_errors.h"
+#include "util-inl.h"
namespace node {
-
-namespace per_process {
-native_module::NativeModuleLoader native_module_loader;
-} // namespace per_process
-
namespace native_module {
-using v8::Array;
-using v8::ArrayBuffer;
using v8::Context;
-using v8::DEFAULT;
using v8::EscapableHandleScope;
using v8::Function;
-using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::Integer;
-using v8::IntegrityLevel;
using v8::Isolate;
using v8::Local;
using v8::Maybe;
using v8::MaybeLocal;
-using v8::Name;
-using v8::None;
using v8::Object;
-using v8::PropertyCallbackInfo;
using v8::Script;
using v8::ScriptCompiler;
using v8::ScriptOrigin;
-using v8::Set;
-using v8::SideEffectType;
using v8::String;
-using v8::Uint8Array;
-using v8::Value;
+
+NativeModuleLoader NativeModuleLoader::instance_;
+
+NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) {
+ LoadJavaScriptSource();
+}
+
+NativeModuleLoader* NativeModuleLoader::GetInstance() {
+ return &instance_;
+}
+
+bool NativeModuleLoader::Exists(const char* id) {
+ return source_.find(id) != source_.end();
+}
+
+Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
+ Isolate* isolate = context->GetIsolate();
+ Local<Object> out = Object::New(isolate);
+ for (auto const& x : source_) {
+ Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
+ out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust();
+ }
+ return out;
+}
+
+Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
+ return config_.ToStringChecked(isolate);
+}
+
+std::vector<std::string> NativeModuleLoader::GetModuleIds() {
+ std::vector<std::string> ids;
+ ids.reserve(source_.size());
+ for (auto const& x : source_) {
+ ids.emplace_back(x.first);
+ }
+ return ids;
+}
void NativeModuleLoader::InitializeModuleCategories() {
if (module_categories_.is_initialized) {
@@ -105,182 +125,52 @@ void NativeModuleLoader::InitializeModuleCategories() {
module_categories_.is_initialized = true;
}
-// TODO(joyeecheung): make these more general and put them into util.h
-Local<Object> MapToObject(Local<Context> context,
- const NativeModuleRecordMap& in) {
- Isolate* isolate = context->GetIsolate();
- Local<Object> out = Object::New(isolate);
- for (auto const& x : in) {
- Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
- out->Set(context, key, x.second.ToStringChecked(isolate)).Check();
- }
- return out;
+const std::set<std::string>& NativeModuleLoader::GetCannotBeRequired() {
+ InitializeModuleCategories();
+ return module_categories_.cannot_be_required;
}
-Local<Set> ToJsSet(Local<Context> context,
- const std::set<std::string>& in) {
- Isolate* isolate = context->GetIsolate();
- Local<Set> out = Set::New(isolate);
- for (auto const& x : in) {
- out->Add(context, OneByteString(isolate, x.c_str(), x.size()))
- .ToLocalChecked();
- }
- return out;
+const std::set<std::string>& NativeModuleLoader::GetCanBeRequired() {
+ InitializeModuleCategories();
+ return module_categories_.can_be_required;
}
-bool NativeModuleLoader::Exists(const char* id) {
- return source_.find(id) != source_.end();
+bool NativeModuleLoader::CanBeRequired(const char* id) {
+ return GetCanBeRequired().count(id) == 1;
}
-void NativeModuleLoader::GetModuleCategories(
- Local<Name> property, const PropertyCallbackInfo<Value>& info) {
- per_process::native_module_loader.InitializeModuleCategories();
-
- Environment* env = Environment::GetCurrent(info);
- Isolate* isolate = env->isolate();
- Local<Context> context = env->context();
- Local<Object> result = Object::New(isolate);
-
- // Copy from the per-process categories
- std::set<std::string> cannot_be_required =
- per_process::native_module_loader.module_categories_.cannot_be_required;
- std::set<std::string> can_be_required =
- per_process::native_module_loader.module_categories_.can_be_required;
-
- if (!env->owns_process_state()) {
- can_be_required.erase("trace_events");
- cannot_be_required.insert("trace_events");
- }
-
- result
- ->Set(context,
- OneByteString(isolate, "cannotBeRequired"),
- ToJsSet(context, cannot_be_required))
- .Check();
- result
- ->Set(context,
- OneByteString(isolate, "canBeRequired"),
- ToJsSet(context, can_be_required))
- .Check();
- info.GetReturnValue().Set(result);
-}
-
-void NativeModuleLoader::GetCacheUsage(
- const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- Isolate* isolate = env->isolate();
- Local<Context> context = env->context();
- Local<Object> result = Object::New(isolate);
- result
- ->Set(env->context(),
- OneByteString(isolate, "compiledWithCache"),
- ToJsSet(context, env->native_modules_with_cache))
- .Check();
- result
- ->Set(env->context(),
- OneByteString(isolate, "compiledWithoutCache"),
- ToJsSet(context, env->native_modules_without_cache))
- .Check();
- args.GetReturnValue().Set(result);
-}
-
-void NativeModuleLoader::ModuleIdsGetter(
- Local<Name> property, const PropertyCallbackInfo<Value>& info) {
- Isolate* isolate = info.GetIsolate();
-
- const NativeModuleRecordMap& source_ =
- per_process::native_module_loader.source_;
- std::vector<Local<Value>> ids;
- ids.reserve(source_.size());
-
- for (auto const& x : source_) {
- ids.emplace_back(OneByteString(isolate, x.first.c_str(), x.first.size()));
- }
-
- info.GetReturnValue().Set(Array::New(isolate, ids.data(), ids.size()));
-}
-
-void NativeModuleLoader::ConfigStringGetter(
- Local<Name> property, const PropertyCallbackInfo<Value>& info) {
- info.GetReturnValue().Set(
- per_process::native_module_loader.GetConfigString(info.GetIsolate()));
-}
-
-Local<Object> NativeModuleLoader::GetSourceObject(
- Local<Context> context) const {
- return MapToObject(context, source_);
-}
-
-Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) const {
- return config_.ToStringChecked(isolate);
-}
-
-NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) {
- LoadJavaScriptSource();
- LoadCodeCache();
+bool NativeModuleLoader::CannotBeRequired(const char* id) {
+ return GetCannotBeRequired().count(id) == 1;
}
-// This is supposed to be run only by the main thread in
-// tools/generate_code_cache.js
-void NativeModuleLoader::GetCodeCache(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- Isolate* isolate = env->isolate();
- CHECK(env->is_main_thread());
-
- CHECK(args[0]->IsString());
- node::Utf8Value id_v(isolate, args[0].As<String>());
- const char* id = *id_v;
-
- const NativeModuleLoader& loader = per_process::native_module_loader;
- MaybeLocal<Uint8Array> ret = loader.GetCodeCache(isolate, id);
- if (!ret.IsEmpty()) {
- args.GetReturnValue().Set(ret.ToLocalChecked());
- }
+NativeModuleCacheMap* NativeModuleLoader::code_cache() {
+ return &code_cache_;
}
-// This is supposed to be run only by the main thread in
-// tools/generate_code_cache.js
-MaybeLocal<Uint8Array> NativeModuleLoader::GetCodeCache(Isolate* isolate,
- const char* id) const {
- EscapableHandleScope scope(isolate);
+ScriptCompiler::CachedData* NativeModuleLoader::GetCodeCache(
+ const char* id) const {
Mutex::ScopedLock lock(code_cache_mutex_);
-
- ScriptCompiler::CachedData* cached_data = nullptr;
const auto it = code_cache_.find(id);
if (it == code_cache_.end()) {
// The module has not been compiled before.
- return MaybeLocal<Uint8Array>();
- }
-
- cached_data = it->second.get();
-
- Local<ArrayBuffer> buf = ArrayBuffer::New(isolate, cached_data->length);
- memcpy(buf->GetContents().Data(), cached_data->data, cached_data->length);
- return scope.Escape(Uint8Array::New(buf, 0, cached_data->length));
-}
-
-void NativeModuleLoader::CompileFunction(
- const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- CHECK(args[0]->IsString());
- node::Utf8Value id(env->isolate(), args[0].As<String>());
-
- MaybeLocal<Function> result = CompileAsModule(env, *id);
- if (!result.IsEmpty()) {
- args.GetReturnValue().Set(result.ToLocalChecked());
+ return nullptr;
}
+ return it->second.get();
}
-MaybeLocal<Function> NativeModuleLoader::CompileAsModule(Environment* env,
- const char* id) {
- std::vector<Local<String>> parameters = {env->exports_string(),
- env->require_string(),
- env->module_string(),
- env->process_string(),
- env->internal_binding_string(),
- env->primordials_string()};
- return per_process::native_module_loader.LookupAndCompile(
- env->context(), id, &parameters, env);
+MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
+ Local<Context> context,
+ const char* id,
+ NativeModuleLoader::Result* result) {
+ Isolate* isolate = context->GetIsolate();
+ std::vector<Local<String>> parameters = {
+ FIXED_ONE_BYTE_STRING(isolate, "exports"),
+ FIXED_ONE_BYTE_STRING(isolate, "require"),
+ FIXED_ONE_BYTE_STRING(isolate, "module"),
+ FIXED_ONE_BYTE_STRING(isolate, "process"),
+ FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
+ FIXED_ONE_BYTE_STRING(isolate, "primordials")};
+ return LookupAndCompile(context, id, &parameters, result);
}
// Returns Local<Function> of the compiled module if return_code_cache
@@ -290,7 +180,7 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
Local<Context> context,
const char* id,
std::vector<Local<String>>* parameters,
- Environment* optional_env) {
+ NativeModuleLoader::Result* result) {
Isolate* isolate = context->GetIsolate();
EscapableHandleScope scope(isolate);
@@ -317,9 +207,9 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
}
}
- const bool use_cache = cached_data != nullptr;
+ const bool has_cache = cached_data != nullptr;
ScriptCompiler::CompileOptions options =
- use_cache ? ScriptCompiler::kConsumeCodeCache
+ has_cache ? ScriptCompiler::kConsumeCodeCache
: ScriptCompiler::kEagerCompile;
ScriptCompiler::Source script_source(source, origin, cached_data);
@@ -346,22 +236,10 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
// it only starts after the Environment is created, so the per_context.js
// will never be in any of these two sets, but the two sets are only for
// testing anyway.
- if (use_cache) {
- if (optional_env != nullptr) {
- // This could happen when Node is run with any v8 flag, but
- // the cache is not generated with one
- if (script_source.GetCachedData()->rejected) {
- optional_env->native_modules_without_cache.insert(id);
- } else {
- optional_env->native_modules_with_cache.insert(id);
- }
- }
- } else {
- if (optional_env != nullptr) {
- optional_env->native_modules_without_cache.insert(id);
- }
- }
+ *result = (has_cache && !script_source.GetCachedData()->rejected)
+ ? Result::kWithCache
+ : Result::kWithoutCache;
// Generate new cache for next compilation
std::unique_ptr<ScriptCompiler::CachedData> new_cached_data(
ScriptCompiler::CreateCodeCacheForFunction(fun));
@@ -373,56 +251,5 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
return scope.Escape(fun);
}
-void NativeModuleLoader::Initialize(Local<Object> target,
- Local<Value> unused,
- Local<Context> context,
- void* priv) {
- Environment* env = Environment::GetCurrent(context);
-
- CHECK(target
- ->SetAccessor(env->context(),
- env->config_string(),
- ConfigStringGetter,
- nullptr,
- MaybeLocal<Value>(),
- DEFAULT,
- None,
- SideEffectType::kHasNoSideEffect)
- .FromJust());
- CHECK(target
- ->SetAccessor(env->context(),
- FIXED_ONE_BYTE_STRING(env->isolate(), "moduleIds"),
- ModuleIdsGetter,
- nullptr,
- MaybeLocal<Value>(),
- DEFAULT,
- None,
- SideEffectType::kHasNoSideEffect)
- .FromJust());
-
- CHECK(target
- ->SetAccessor(
- env->context(),
- FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"),
- GetModuleCategories,
- nullptr,
- env->as_callback_data(),
- DEFAULT,
- None,
- SideEffectType::kHasNoSideEffect)
- .FromJust());
-
- env->SetMethod(
- target, "getCacheUsage", NativeModuleLoader::GetCacheUsage);
- env->SetMethod(
- target, "compileFunction", NativeModuleLoader::CompileFunction);
- env->SetMethod(target, "getCodeCache", NativeModuleLoader::GetCodeCache);
- // internalBinding('native_module') should be frozen
- target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).Check();
-}
-
} // namespace native_module
} // namespace node
-
-NODE_MODULE_CONTEXT_AWARE_INTERNAL(
- native_module, node::native_module::NativeModuleLoader::Initialize)