Skip to content

Commit 50b3357

Browse files
author
Matheus Marchini
committed
src: fix context inpection for V8 6.8
V8 6.8 replaces Closure inside Context with ScopeInfo. Those are minimal changes to adopt llnode to the new behavior. Ref: https://chromium-review.googlesource.com/#/c/785151/ Fixes: #193 PR-URL: #201 Reviewed-By: Joyee Cheung <[email protected]>
1 parent d348eff commit 50b3357

File tree

5 files changed

+67
-20
lines changed

5 files changed

+67
-20
lines changed

src/llv8-constants.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,9 @@ void ScopeInfo::Load() {
244244

245245

246246
void Context::Load() {
247-
kClosureIndex =
248-
LoadConstant("class_Context__closure_index__int", "context_idx_closure");
247+
kClosureIndex = LoadConstant("class_Context__closure_index__int",
248+
"context_idx_closure", -1);
249+
kScopeInfoIndex = LoadConstant("context_idx_scope_info", -1);
249250
kPreviousIndex =
250251
LoadConstant("class_Context__previous_index__int", "context_idx_prev");
251252
// TODO (mmarchini) change LoadConstant to accept variable arguments, a list

src/llv8-constants.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,22 @@ class Context : public Module {
199199
CONSTANTS_DEFAULT_METHODS(Context);
200200

201201
int64_t kClosureIndex;
202+
int64_t kScopeInfoIndex;
202203
int64_t kGlobalObjectIndex;
203204
int64_t kPreviousIndex;
204205
int64_t kNativeIndex;
205206
int64_t kEmbedderDataIndex;
206207
int64_t kMinContextSlots;
207208

209+
inline bool hasClosure() {
210+
// NOTE (mmarchini): V8 6.8 replaced the closure field (which was a
211+
// JSFunction) with a scope_info field (which is a ScopeInfo). The change
212+
// made it easier to get the scope info for a context, but removed our
213+
// ability to get the outer function for a given context. We can still get
214+
// the outer context through the previous field though.
215+
return kClosureIndex != -1;
216+
}
217+
208218
protected:
209219
void Load();
210220
};

src/llv8.cc

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ std::string JSFunction::Inspect(InspectOptions* options, Error& err) {
392392
std::string context_str = context.Inspect(err);
393393
if (err.Fail()) return std::string();
394394

395-
if (!context_str.empty()) res += "{\n" + context_str + "}";
395+
if (!context_str.empty()) res += ":" + context_str;
396396

397397
if (options->print_source) {
398398
SharedFunctionInfo info = Info(err);
@@ -1047,24 +1047,31 @@ std::string FixedArray::InspectContents(int length, Error& err) {
10471047
return res;
10481048
}
10491049

1050+
HeapObject Context::GetScopeInfo(Error& err) {
1051+
if (v8()->context()->kScopeInfoIndex != -1) {
1052+
return FixedArray::Get<HeapObject>(v8()->context()->kScopeInfoIndex, err);
1053+
}
1054+
JSFunction closure = Closure(err);
1055+
if (err.Fail()) return HeapObject();
1056+
1057+
SharedFunctionInfo info = closure.Info(err);
1058+
if (err.Fail()) return HeapObject();
1059+
1060+
return info.GetScopeInfo(err);
1061+
}
10501062

10511063
std::string Context::Inspect(Error& err) {
1052-
std::string res;
10531064
// Not enough postmortem information, return bare minimum
10541065
if (v8()->shared_info()->kScopeInfoOffset == -1 &&
10551066
v8()->shared_info()->kNameOrScopeInfoOffset == -1)
1056-
return res;
1067+
return std::string();
10571068

1058-
Value previous = Previous(err);
1059-
if (err.Fail()) return std::string();
1069+
std::string res = "<Context: {\n";
10601070

1061-
JSFunction closure = Closure(err);
1062-
if (err.Fail()) return std::string();
1063-
1064-
SharedFunctionInfo info = closure.Info(err);
1071+
Value previous = Previous(err);
10651072
if (err.Fail()) return std::string();
10661073

1067-
HeapObject scope_obj = info.GetScopeInfo(err);
1074+
HeapObject scope_obj = GetScopeInfo(err);
10681075
if (err.Fail()) return std::string();
10691076

10701077
ScopeInfo scope(scope_obj);
@@ -1082,11 +1089,14 @@ std::string Context::Inspect(Error& err) {
10821089
if (heap_previous.Check()) {
10831090
char tmp[128];
10841091
snprintf(tmp, sizeof(tmp), " (previous)=0x%016" PRIx64, previous.raw());
1085-
res += tmp;
1092+
res += std::string(tmp) + ":<Context>,";
10861093
}
10871094

10881095
if (!res.empty()) res += "\n";
1089-
{
1096+
1097+
if (v8()->context()->hasClosure()) {
1098+
JSFunction closure = Closure(err);
1099+
if (err.Fail()) return std::string();
10901100
char tmp[128];
10911101
snprintf(tmp, sizeof(tmp), " (closure)=0x%016" PRIx64 " {",
10921102
closure.raw());
@@ -1095,6 +1105,21 @@ std::string Context::Inspect(Error& err) {
10951105
InspectOptions options;
10961106
res += closure.Inspect(&options, err) + "}";
10971107
if (err.Fail()) return std::string();
1108+
} else {
1109+
char tmp[128];
1110+
snprintf(tmp, sizeof(tmp), " (scope_info)=0x%016" PRIx64,
1111+
scope.raw());
1112+
1113+
res += std::string(tmp) + ":<ScopeInfo";
1114+
1115+
Error function_name_error;
1116+
HeapObject maybe_function_name = scope.MaybeFunctionName(function_name_error);
1117+
1118+
if (function_name_error.Success()) {
1119+
res += ": for function " + String(maybe_function_name).ToString(err);
1120+
}
1121+
1122+
res += ">";
10981123
}
10991124

11001125
int param_count = param_count_smi.GetValue();
@@ -1116,7 +1141,7 @@ std::string Context::Inspect(Error& err) {
11161141
if (err.Fail()) return std::string();
11171142
}
11181143

1119-
return res;
1144+
return res + " }>";
11201145
}
11211146

11221147

src/llv8.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ class Context : public FixedArray {
382382
public:
383383
V8_VALUE_DEFAULT_METHODS(Context, FixedArray)
384384

385-
inline JSFunction Closure(Error& err);
385+
inline HeapObject GetScopeInfo(Error& err);
386386
inline Value Previous(Error& err);
387387
inline Value Native(Error& err);
388388
inline bool IsNative(Error& err);
@@ -391,6 +391,9 @@ class Context : public FixedArray {
391391
inline Value ContextSlot(int index, Error& err);
392392

393393
std::string Inspect(Error& err);
394+
395+
private:
396+
inline JSFunction Closure(Error& err);
394397
};
395398

396399
class ScopeInfo : public FixedArray {

test/plugin/inspect-test.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const hashMapTests = {
5151
const arrowSource = 'source:\n' +
5252
'function c.hashmap.(anonymous function)(a,b)=>{a+b}\n' +
5353
'>';
54-
54+
5555
t.ok(lines.includes(arrowSource),
5656
'hashmap[25] should have the correct function source');
5757
cb(null);
@@ -305,14 +305,22 @@ const hashMapTests = {
305305

306306
const contextTests = {
307307
'previous': {
308-
re: /\(previous\)/,
308+
re: /\(previous\)=(0x[0-9a-f]+)[^\n]+/,
309309
desc: '.(previous)'
310310
},
311311
'closure': {
312-
re: /\(closure\)=(0x[0-9a-f]+)[^\n]+function: closure/i,
312+
re: /(\((?:closure|scope_info)\)=0x[0-9a-f]+)[^\n]+/i,
313313
desc: '.(closure)',
314314
validator(t, sess, addresses, name, cb) {
315-
const address = addresses[name];
315+
const type = addresses[name].split("=")[0];
316+
let address = undefined;
317+
if (type === "(closure)") {
318+
address = addresses[name].split("=")[1];
319+
} else if (type === "(scope_info)") {
320+
address = addresses["previous"];
321+
} else {
322+
return cb(new Error("unknown field"));
323+
}
316324
sess.send(`v8 inspect ${address}`);
317325
sess.linesUntil(/}>/, (err, lines) => {
318326
if (err) return cb(err);

0 commit comments

Comments
 (0)