Skip to content

Commit

Permalink
src: inspect context objects (Node.js v10.x+)
Browse files Browse the repository at this point in the history
This patch teaches llnode how to inspect Context objects. This is useful
to inspect context variables.

Fix: nodejs#211
  • Loading branch information
Matheus Marchini committed Aug 20, 2018
1 parent d680b80 commit 8676013
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
4 changes: 4 additions & 0 deletions src/llv8-constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,9 @@ void Types::Load() {
kFirstJSObjectType =
LoadConstant("type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE");

kFirstContextType = LoadConstant("FirstContextType");
kLastContextType = LoadConstant("LastContextType");

kHeapNumberType = LoadConstant("type_HeapNumber__HEAP_NUMBER_TYPE");
kMapType = LoadConstant("type_Map__MAP_TYPE");
kGlobalObjectType =
Expand All @@ -508,6 +511,7 @@ void Types::Load() {
kSharedFunctionInfoType =
LoadConstant("type_SharedFunctionInfo__SHARED_FUNCTION_INFO_TYPE");
kScriptType = LoadConstant("type_Script__SCRIPT_TYPE");
kScopeInfoType = LoadConstant("type_ScopeInfo__SCOPE_INFO_TYPE");

if (kJSAPIObjectType == -1) {
common_->Load();
Expand Down
4 changes: 4 additions & 0 deletions src/llv8-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ class Types : public Module {
int64_t kFirstNonstringType;
int64_t kFirstJSObjectType;

int64_t kFirstContextType;
int64_t kLastContextType;

int64_t kHeapNumberType;
int64_t kMapType;
int64_t kGlobalObjectType;
Expand All @@ -484,6 +487,7 @@ class Types : public Module {
int64_t kJSDateType;
int64_t kSharedFunctionInfoType;
int64_t kScriptType;
int64_t kScopeInfoType;

protected:
void Load();
Expand Down
46 changes: 31 additions & 15 deletions src/llv8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,15 @@ std::string JSFunction::Inspect(InspectOptions* options, Error& err) {
snprintf(tmp, sizeof(tmp), "\n context=0x%016" PRIx64, context.raw());
res += tmp;

std::string context_str = context.Inspect(err);
if (err.Fail()) return std::string();
{
InspectOptions ctx_options;
ctx_options.detailed = true;
ctx_options.indent_depth = options->indent_depth + 1;
std::string context_str = context.Inspect(&ctx_options, err);
if (err.Fail()) return std::string();

if (!context_str.empty()) res += ":" + context_str;
if (!context_str.empty()) res += ":" + context_str;
}

if (options->print_source) {
SharedFunctionInfo info = Info(err);
Expand Down Expand Up @@ -821,6 +826,12 @@ std::string HeapObject::Inspect(InspectOptions* options, Error& err) {
return pre + str.Inspect(options, err);
}

if (type >= v8()->types()->kFirstContextType &&
type <= v8()->types()->kLastContextType) {
Context ctx(this);
return pre + ctx.Inspect(options, err);
}

if (type == v8()->types()->kFixedArrayType) {
FixedArray arr(this);
return pre + arr.Inspect(options, err);
Expand Down Expand Up @@ -1060,13 +1071,19 @@ HeapObject Context::GetScopeInfo(Error& err) {
return info.GetScopeInfo(err);
}

std::string Context::Inspect(Error& err) {
std::string Context::Inspect(InspectOptions* options, Error& err) {
// Not enough postmortem information, return bare minimum
if (v8()->shared_info()->kScopeInfoOffset == -1 &&
v8()->shared_info()->kNameOrScopeInfoOffset == -1)
return std::string();

std::string res = "<Context: {\n";
std::string res = "<Context";

if (!options->detailed) {
return res + ">";
}

res += ": {\n";

Value previous = Previous(err);
if (err.Fail()) return std::string();
Expand All @@ -1083,12 +1100,10 @@ std::string Context::Inspect(Error& err) {
Smi local_count_smi = scope.ContextLocalCount(err);
if (err.Fail()) return std::string();

InspectOptions options;

HeapObject heap_previous = HeapObject(previous);
if (heap_previous.Check()) {
char tmp[128];
snprintf(tmp, sizeof(tmp), " (previous)=0x%016" PRIx64, previous.raw());
snprintf(tmp, sizeof(tmp), (options->get_indent_spaecs() + "(previous)=0x%016" PRIx64).c_str(), previous.raw());
res += std::string(tmp) + ":<Context>,";
}

Expand All @@ -1098,16 +1113,16 @@ std::string Context::Inspect(Error& err) {
JSFunction closure = Closure(err);
if (err.Fail()) return std::string();
char tmp[128];
snprintf(tmp, sizeof(tmp), " (closure)=0x%016" PRIx64 " {",
snprintf(tmp, sizeof(tmp), (options->get_indent_spaecs() + "(closure)=0x%016" PRIx64 " {").c_str(),
closure.raw());
res += tmp;

InspectOptions options;
res += closure.Inspect(&options, err) + "}";
InspectOptions closure_options;
res += closure.Inspect(&closure_options, err) + "}";
if (err.Fail()) return std::string();
} else {
char tmp[128];
snprintf(tmp, sizeof(tmp), " (scope_info)=0x%016" PRIx64,
snprintf(tmp, sizeof(tmp), (options->get_indent_spaecs() + "(scope_info)=0x%016" PRIx64).c_str(),
scope.raw());

res += std::string(tmp) + ":<ScopeInfo";
Expand All @@ -1131,17 +1146,18 @@ std::string Context::Inspect(Error& err) {

if (!res.empty()) res += ",\n";

res += " " + name.ToString(err) + "=";
res += options->get_indent_spaecs() + name.ToString(err) + "=";
if (err.Fail()) return std::string();

Value value = ContextSlot(i, err);
if (err.Fail()) return std::string();

res += value.Inspect(&options, err);
InspectOptions val_options;
res += value.Inspect(&val_options, err);
if (err.Fail()) return std::string();
}

return res + " }>";
return res + "}>";
}


Expand Down
10 changes: 8 additions & 2 deletions src/llv8.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@ class Value {
: detailed(false),
print_map(false),
print_source(false),
length(kLength) {}
length(kLength),
indent_depth(1) {}

static const unsigned int kLength = 16;
static const unsigned int kIndentSize = 2;
inline std::string get_indent_spaecs() {
return std::string(indent_depth * kIndentSize, ' ');
}

bool detailed;
bool print_map;
bool print_source;
unsigned int length;
unsigned int indent_depth;
};

Value(const Value& v) = default;
Expand Down Expand Up @@ -390,7 +396,7 @@ class Context : public FixedArray {
inline T GetEmbedderData(int64_t index, Error& err);
inline Value ContextSlot(int index, Error& err);

std::string Inspect(Error& err);
std::string Inspect(InspectOptions *options, Error& err);

private:
inline JSFunction Closure(Error& err);
Expand Down

0 comments on commit 8676013

Please sign in to comment.