Я хочу создать своего рода локализованную область действия, которая будет действовать как набор глобальных элементов внутри определенной функции, но я хочу наследовать все глобальные переменные, которые могут уже существовать.
Однако должен быть более простой способ сделать это, чем то, что я делаю.
То, что я делаю прямо сейчас, это преобразовать объект области, который я хочу использовать, в строку, состоящую из объявлений и назначений var, в javascript. Я помещаю это внутри анонимной функции, которая возвращает мой исходный код функции и вызывает анонимную функцию, чтобы дать мне внутреннюю функцию.
Макрос MAKESTRING использует строковый поток для определения строки
std::prefix_code = convert_object_to_vars(scope);
std::code = MAKESTRING("(function() { " << prefix_code << "return (" << fdefinition << "); })()");
v8::TryCatch try_catch;
v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(_isolate, code.c_str()));
if (try_catch.HasCaught())
return v8::Undefined(_isolate);
if (script.IsEmpty())
return v8::Undefined(_isolate);
v8::Local<v8::Value> result = script->Run();
if (try_catch.HasCaught())
return v8::Undefined(_isolate);
if (!result->IsFunction())
return v8::Undefined(_isolate);
return result
Переменная scope - это просто объект v8 :: Object, состоящий из пар значений ключа, описывающий различные переменные, которые существуют в области и их начальные значения.
Функция convert_object_to_vars - это то, где вещи становятся dicey... хотя это, похоже, работает, я должен явно писать код в функции convert для обработки каждого нового типа, который я хочу поддерживать, и по мере добавления дополнительных пользовательских типов эта функция быстро растет по сложности, поэтому я не уверен, что это долгосрочное решение. Кроме того, большая часть кода на convert_object_to_vars также должна быть реплицирована в другую функцию, которая возвращает удобочитаемое представление такого объекта.
Должен быть более простой способ.
Недавно я столкнулся с этой проблемой при разработке собственного дополнения к потоковым пулам.
Ключом к тому, чтобы это работать, - это настроить контекст, который будет выполнять функция, с помощью глобальных переменных, которые вы хотите получить в функции.
Это должно произойти до того, как вы скомпилируете и запустите стробированную функцию. Я привел небольшой пример ниже. myGlobalProperty
будет доступен как глобальный внутри функции, потому что он был скомпилирован и запущен в текущем введенном контексте.
// configure context before executing function
HandleScope scope;
Handle<Object> contextObject = Context::GetCurrent()->Global();
contextObject->Set(String::NewSymbol("myGlobalProperty"), Object::New());
// turn function into string
String::Utf8Value funcStr(functionToExecute->ToString());
string funcToExe(*funcStr);
funcToExe.insert(0, "(");
funcToExe.append(")()");
// compile and run the function
// this will execute within the currently entered and configured context
Handle<Script> functionScript = Script::New(String::New(funcToExe.c_str()));
functionScript->Run();
Если вы хотите получить доступ к глобальным переменным после выполнения функции. Вам нужно будет получить к ним доступ через контекст, как показано ниже:
Handle<Value> myGlobal = contextObject->Get(String::NewSymbol("myGlobalProperty"));
with
.