Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/llv8-constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ void ScopeInfo::Load() {


void Context::Load() {
kClosureIndex =
LoadConstant("class_Context__closure_index__int", "context_idx_closure");
kClosureIndex = LoadConstant("class_Context__closure_index__int",
"context_idx_closure", -1);
kScopeInfoIndex = LoadConstant("context_idx_scope_info", -1);
kPreviousIndex =
LoadConstant("class_Context__previous_index__int", "context_idx_prev");
// TODO (mmarchini) change LoadConstant to accept variable arguments, a list
Expand Down Expand Up @@ -486,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 @@ -507,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
5 changes: 5 additions & 0 deletions src/llv8-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class Context : public Module {
CONSTANTS_DEFAULT_METHODS(Context);

int64_t kClosureIndex;
int64_t kScopeInfoIndex;
int64_t kGlobalObjectIndex;
int64_t kPreviousIndex;
int64_t kNativeIndex;
Expand Down Expand Up @@ -465,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 @@ -483,6 +487,7 @@ class Types : public Module {
int64_t kJSDateType;
int64_t kSharedFunctionInfoType;
int64_t kScriptType;
int64_t kScopeInfoType;

protected:
void Load();
Expand Down
87 changes: 64 additions & 23 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 += "{\n" + 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 @@ -1047,24 +1058,37 @@ std::string FixedArray::InspectContents(int length, Error& err) {
return res;
}

HeapObject Context::GetScopeInfo(Error& err) {
if (v8()->context()->kScopeInfoIndex != -1) {
return FixedArray::Get<HeapObject>(v8()->context()->kScopeInfoIndex, err);
}
JSFunction closure = Closure(err);
if (err.Fail()) return HeapObject();

std::string Context::Inspect(Error& err) {
std::string res;
SharedFunctionInfo info = closure.Info(err);
if (err.Fail()) return HeapObject();

return info.GetScopeInfo(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 res;
return std::string();

Value previous = Previous(err);
if (err.Fail()) return std::string();
std::string res = "<Context";

JSFunction closure = Closure(err);
if (err.Fail()) return std::string();
if (!options->detailed) {
return res + ">";
}

SharedFunctionInfo info = closure.Info(err);
res += ": {\n";

Value previous = Previous(err);
if (err.Fail()) return std::string();

HeapObject scope_obj = info.GetScopeInfo(err);
HeapObject scope_obj = GetScopeInfo(err);
if (err.Fail()) return std::string();

ScopeInfo scope(scope_obj);
Expand All @@ -1076,25 +1100,41 @@ 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());
res += tmp;
snprintf(tmp, sizeof(tmp), (options->get_indent_spaecs() + "(previous)=0x%016" PRIx64).c_str(), previous.raw());
res += std::string(tmp) + ":<Context>,";
}

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

if (v8()->context()->kClosureIndex != -1) {
Comment thread
mmarchini marked this conversation as resolved.
Outdated
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), (options->get_indent_spaecs() + "(scope_info)=0x%016" PRIx64).c_str(),
scope.raw());

res += std::string(tmp) + ":<ScopeInfo";

Error function_name_error;
HeapObject maybe_function_name = scope.MaybeFunctionName(function_name_error);

if (function_name_error.Success()) {
res += ": for function " + String(maybe_function_name).ToString(err);
}

res += ">";
}

int param_count = param_count_smi.GetValue();
Expand All @@ -1106,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
15 changes: 12 additions & 3 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() {
Comment thread
mmarchini marked this conversation as resolved.
Outdated
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 @@ -382,15 +388,18 @@ class Context : public FixedArray {
public:
V8_VALUE_DEFAULT_METHODS(Context, FixedArray)

inline JSFunction Closure(Error& err);
inline HeapObject GetScopeInfo(Error& err);
inline Value Previous(Error& err);
inline Value Native(Error& err);
inline bool IsNative(Error& err);
template <class T>
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);
};

class ScopeInfo : public FixedArray {
Expand Down
16 changes: 12 additions & 4 deletions test/plugin/inspect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const hashMapTests = {
const arrowSource = 'source:\n' +
'function c.hashmap.(anonymous function)(a,b)=>{a+b}\n' +
'>';

t.ok(lines.includes(arrowSource),
'hashmap[25] should have the correct function source');
cb(null);
Expand Down Expand Up @@ -305,14 +305,22 @@ const hashMapTests = {

const contextTests = {
'previous': {
re: /\(previous\)/,
re: /\(previous\)=(0x[0-9a-f]+)[^\n]+/,
desc: '.(previous)'
},
'closure': {
re: /\(closure\)=(0x[0-9a-f]+)[^\n]+function: closure/i,
re: /(\((?:closure|scope_info)\)=0x[0-9a-f]+)[^\n]+/i,
desc: '.(closure)',
validator(t, sess, addresses, name, cb) {
const address = addresses[name];
const type = addresses[name].split("=")[0];
let address = undefined;
if (type === "(closure)") {
address = addresses[name].split("=")[1];
} else if (type === "(scope_info)") {
address = addresses["previous"];
} else {
return cb(new Error("unknown field"));
}
sess.send(`v8 inspect ${address}`);
sess.linesUntil(/}>/, (err, lines) => {
if (err) return cb(err);
Expand Down