Google V8: доступ к локальным переменным в переполнении стека

Кто-нибудь знает, как я мог искать локальные переменные в вызове вложенной функции из C ++?
Рассмотрим следующий пример:

// e.g. a global variable in the browser
var global = "global_value";

function foo(){
var global = "local_value";
myCppFunction("global", global);
}

foo();

Мой вопрос сейчас заключается в том, как в реализации myCppFunction Я мог получить доступ к локальной переменной функции «global» (НЕ значение, это было бы дано вторым параметром) из ‘foo’?

Handle<Value> MyCppFunction(const Arguments& args){
Local<String> varName = args[0]->ToString();
Local<String> varValue = args[1]->ToString(); // this holds "local_value"// how to access the variable "global" in the scope of 'foo' ?
}

4

Решение

Мне удалось выяснить это самостоятельно. Смотрите пример ниже, чтобы найти значение в стеке (а также заменить его — здесь на примере строковой переменной).

Два замечания заранее:

  • Я не проверял это на нежелательное поведение, за исключением тех случаев, когда я использую это в своей магистерской диссертации — там (могут) быть драконы.
  • Я не знаю точно, почему в моих тестах sfl.FindJavaScriptFrame(0) дает желаемый кадр стека — но, поскольку он работает независимо от глубины вызова, я подозреваю, что кадр стека, индексированный 0, всегда будет кадром непосредственного вызывающего (в моем случае я знаю, что хочу именно это).

И код:

// Prepare identification of the variable,assuming varName as in the question
// More convenient conversions would be appreciated, at least by me
Local<String> varName = args[0]->ToString();
std::string varStr = *String::AsciiValue(varName);
// I'm using 'namespace i = internal;' (within v8-namespace)
i::Vector<const char> tmpVar(varStr.data(), varStr.length());
i::Handle<i::String> varIStr = i::Isolate::Current()->factory()->NewStringFromAscii(tmpVar, i::TENURED);

// Now hunt down the stack frame of interest, be sure to consider my remarks above
i::StackFrameLocator sfl;
// Comment from the code: The caller must guarantee that such a frame exists.
i::JavaScriptFrame* jsf = sfl.FindJavaScriptFrame(0);
// create some replacement
i::Vector<const char> tmp("there you go", 12);
i::Handle<i::String> insert = i::Isolate::Current()->factory()->NewStringFromAscii(tmp, i::TENURED);
i::Object* insertObj = insert->ToObjectChecked();

// by the help of JavaScriptFrame::Print I came up with this:
i::Object* fun = jsf->function();
if (fun->IsJSFunction()){
i::Handle<i::ScopeInfo> scope_info(i::ScopeInfo::Empty());
i::Handle<i::SharedFunctionInfo> shared((i::JSFunction::cast(fun))->shared());
scope_info = i::Handle<i::ScopeInfo>(shared->scope_info());
i::Object* script_obj = shared->script();
if (script_obj->IsScript()) {
int stack_locals_count = scope_info->StackLocalCount();
for (int i = 0; i < stack_locals_count; i++) {
if (scope_info->StackLocalName(i)->Equals(*varIStr)){
// replace the value on the stack
jsf->SetExpression(i,insertObj);
}
}
}
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]