【问题标题】:V8 Cannot set ObjectTemplate with name "console"V8 无法使用名称“控制台”设置 ObjectTemplate
【发布时间】:2018-04-04 09:18:56
【问题描述】:

我尝试设置一个名为控制台的全局对象,但该特定名称会导致崩溃,在我看来,它似乎在告诉我该对象已经存在。我可以将其设置为其他任何内容。为什么我不能将对象设置为“控制台”?

V8 版本为 6.5.254.6

错误

# Fatal error in ../../src/objects.cc, line 6007
# Debug check failed: !it.IsFound().

代码片段

isolate->Enter();
v8::HandleScope handle_scope(isolate);

// Create globals
auto globalObj = v8::ObjectTemplate::New(isolate);

// Create console object
auto consoleObj = v8::ObjectTemplate::New(isolate);

// Log
auto logcb = [](V8CallbackArgs args) {
    auto& log = Log::Instance();
    for (size_t i = 1; i < args.Length(); i++)
        log << *v8::String::Utf8Value(args[i]);
    log << std::endl;
};
consoleObj->Set(v8::String::NewFromUtf8(isolate, "log"), v8::FunctionTemplate::New(isolate, logcb));

// Set global object
globalObj->Set(v8::String::NewFromUtf8(isolate, "console"), consoleObj); // nonono cannot have it console, con is ok though

// Create script context
context = v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>(isolate, v8::Context::New(isolate, nullptr, globalObj));

{
    v8::Context::Scope context_scope(context.Get(isolate));
    v8::TryCatch tc(isolate);

    auto source = v8::String::NewFromUtf8(src.c_str());
    auto script = v8::Script::Compile(source);

    if (script->Run().IsEmpty() && CV8ScriptRuntime::isDebug) {
        v8loge "Error loading script \"" << filepath << "\n" << std::endl
            << "Exception: " << *v8::String::Utf8Value(tc.Exception()) << std::endl
            << "Stack trace: " << *v8::String::Utf8Value(tc.StackTrace()) << std::endl << Log::White;
    }
}

【问题讨论】:

  • 你的观察是正确的。你有什么问题?
  • 为什么不能设置名称为“console”的对象,如果是预定义的,可以取消设置吗?当我尝试设置名称为“控制台”的对象时,我发布了我得到的错误。在我看来,初始化 V8 脚本时“控制台”对象已经存在。但据我所知,v8 不应该默认设置控制台对象。

标签: c++ v8


【解决方案1】:

你的观察是正确的。当 V8 初始化一个 Context 时,它会在其中安装一个全局 console 对象,并假设(由检查保护)具有该名称的属性尚不存在。当您提供自己的“控制台”时,该检查将失败。

如果您想覆盖 V8 的内置 console,您必须先创建 Context(通过 v8::Context::New),然后删除(或覆盖)其全局对象上的 console 属性。

如果您只想在嵌入器中拥有一个 console 对象,就像您从浏览器中知道的那样,那么我很高兴地通知您,这项工作已经完成,您可以简单地使用它:- )

【讨论】:

  • 如何才能删除或覆盖具体的console.log函数?
  • 你已经在globalObj中有全局对象;您可以使用v8::ObjectGet 方法获取其“控制台”对象,然后使用Delete 删除其“日志”方法或Set 覆盖它。或者你可以简单地在你的新上下文中执行脚本“delete console.log”。
  • 有没有办法在没有控制台对象预设的情况下初始化上下文?
  • 不,抱歉。它像其他内置程序一样内置。
猜你喜欢
  • 1970-01-01
  • 2018-09-25
  • 2013-12-21
  • 2017-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-18
相关资源
最近更新 更多