-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: add
node_modules.h
for module loader
- Loading branch information
Showing
14 changed files
with
241 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include "node_modules.h" | ||
#include "base_object-inl.h" | ||
#include "node_errors.h" | ||
#include "node_external_reference.h" | ||
#include "util-inl.h" | ||
#include "v8-fast-api-calls.h" | ||
#include "v8.h" | ||
|
||
namespace node { | ||
namespace modules { | ||
|
||
using v8::CFunction; | ||
using v8::Context; | ||
using v8::FastOneByteString; | ||
using v8::FunctionCallbackInfo; | ||
using v8::HandleScope; | ||
using v8::Isolate; | ||
using v8::Local; | ||
using v8::MaybeLocal; | ||
using v8::NewStringType; | ||
using v8::Object; | ||
using v8::ObjectTemplate; | ||
using v8::String; | ||
using v8::Value; | ||
|
||
void BindingData::MemoryInfo(MemoryTracker* tracker) const { | ||
tracker->TrackField("package_json_files", package_json_files_); | ||
} | ||
|
||
BindingData::BindingData(Realm* realm, v8::Local<v8::Object> object) | ||
: SnapshotableObject(realm, object, type_int) { | ||
package_json_files_ = | ||
v8::Global<v8::Map>(realm->isolate(), v8::Map::New(realm->isolate())); | ||
object | ||
->Set(realm->context(), | ||
FIXED_ONE_BYTE_STRING(realm->isolate(), "packageJsonFiles"), | ||
package_json_files_.Get(realm->isolate())) | ||
.Check(); | ||
|
||
package_json_files_.SetWeak(); | ||
} | ||
|
||
bool BindingData::PrepareForSerialization(v8::Local<v8::Context> context, | ||
v8::SnapshotCreator* creator) { | ||
package_json_files_.Reset(); | ||
// Return true because we need to maintain the reference to the binding from | ||
// JS land. | ||
return true; | ||
} | ||
|
||
InternalFieldInfoBase* BindingData::Serialize(int index) { | ||
DCHECK_IS_SNAPSHOT_SLOT(index); | ||
InternalFieldInfo* info = | ||
InternalFieldInfoBase::New<InternalFieldInfo>(type()); | ||
return info; | ||
} | ||
|
||
void BindingData::Deserialize(v8::Local<v8::Context> context, | ||
v8::Local<v8::Object> holder, | ||
int index, | ||
InternalFieldInfoBase* info) { | ||
DCHECK_IS_SNAPSHOT_SLOT(index); | ||
v8::HandleScope scope(context->GetIsolate()); | ||
Realm* realm = Realm::GetCurrent(context); | ||
BindingData* binding = realm->AddBindingData<BindingData>(holder); | ||
CHECK_NOT_NULL(binding); | ||
} | ||
|
||
void BindingData::ReadPackageJSON(const FunctionCallbackInfo<Value>& args) { | ||
CHECK_GE(args.Length(), 1); | ||
CHECK(args[0]->IsString()); | ||
|
||
Realm* realm = Realm::GetCurrent(args); | ||
auto isolate = realm->isolate(); | ||
auto env = realm->env(); | ||
auto context = realm->context(); | ||
auto binding_data = realm->GetBindingData<BindingData>(); | ||
auto package_json_files_ = binding_data->package_json_files_.Get(isolate); | ||
|
||
Utf8Value path(isolate, args[0]); | ||
THROW_IF_INSUFFICIENT_PERMISSIONS( | ||
env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); | ||
|
||
if (strlen(*path) != path.length()) { | ||
return; // Contains a nul byte. | ||
} | ||
|
||
Local<Value> cache_key = | ||
ToV8Value(context, path.ToStringView(), isolate).ToLocalChecked(); | ||
MaybeLocal<Value> maybe_existing = | ||
package_json_files_->Get(context, cache_key); | ||
Local<Value> existing_value; | ||
if (maybe_existing.ToLocal(&existing_value) && existing_value->IsString()) { | ||
return args.GetReturnValue().Set(existing_value); | ||
} | ||
|
||
uv_fs_t open_req; | ||
const int fd = uv_fs_open(nullptr, &open_req, *path, O_RDONLY, 0, nullptr); | ||
uv_fs_req_cleanup(&open_req); | ||
|
||
if (fd < 0) { | ||
return; | ||
} | ||
|
||
auto defer_close = OnScopeLeave([fd]() { | ||
uv_fs_t close_req; | ||
CHECK_EQ(0, uv_fs_close(nullptr, &close_req, fd, nullptr)); | ||
uv_fs_req_cleanup(&close_req); | ||
}); | ||
|
||
const size_t kBlockSize = 32 << 10; | ||
std::vector<char> chars; | ||
int64_t offset = 0; | ||
ssize_t numchars; | ||
do { | ||
const size_t start = chars.size(); | ||
chars.resize(start + kBlockSize); | ||
|
||
uv_buf_t buf; | ||
buf.base = &chars[start]; | ||
buf.len = kBlockSize; | ||
|
||
uv_fs_t read_req; | ||
numchars = uv_fs_read(nullptr, &read_req, fd, &buf, 1, offset, nullptr); | ||
uv_fs_req_cleanup(&read_req); | ||
|
||
if (numchars < 0) { | ||
return; | ||
} | ||
offset += numchars; | ||
} while (static_cast<size_t>(numchars) == kBlockSize); | ||
|
||
size_t start = 0; | ||
if (offset >= 3 && 0 == memcmp(chars.data(), "\xEF\xBB\xBF", 3)) { | ||
start = 3; // Skip UTF-8 BOM. | ||
} | ||
|
||
auto content = | ||
ToV8Value( | ||
context, std::string_view(&chars[start], offset - start), isolate) | ||
.ToLocalChecked(); | ||
USE(package_json_files_->Set(context, cache_key, content)); | ||
args.GetReturnValue().Set(content); | ||
} | ||
|
||
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data, | ||
Local<ObjectTemplate> target) { | ||
Isolate* isolate = isolate_data->isolate(); | ||
SetMethod(isolate, target, "readPackageJSON", ReadPackageJSON); | ||
} | ||
|
||
void BindingData::CreatePerContextProperties(Local<Object> target, | ||
Local<Value> unused, | ||
Local<Context> context, | ||
void* priv) { | ||
Realm* realm = Realm::GetCurrent(context); | ||
realm->AddBindingData<BindingData>(target); | ||
} | ||
|
||
void BindingData::RegisterExternalReferences( | ||
ExternalReferenceRegistry* registry) { | ||
registry->Register(ReadPackageJSON); | ||
} | ||
|
||
} // namespace modules | ||
} // namespace node | ||
|
||
NODE_BINDING_CONTEXT_AWARE_INTERNAL( | ||
modules, node::modules::BindingData::CreatePerContextProperties) | ||
NODE_BINDING_PER_ISOLATE_INIT( | ||
modules, node::modules::BindingData::CreatePerIsolateProperties) | ||
NODE_BINDING_EXTERNAL_REFERENCE( | ||
modules, node::modules::BindingData::RegisterExternalReferences) |
Oops, something went wrong.