Search code examples
c++v8

V8 Cannot set ObjectTemplate with name "console"


I try to set a global object named console, but that specific name causes a crash and to me it seems like it's telling me that the object already exists. I can though set it to anything else. Why can I not set the object to name "console"?

V8 Version is 6.5.254.6

Error

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

Code Snippet

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;
    }
}

Solution

  • Your observation is correct. When V8 initializes a Context, it installs a global console object into it, and assumes (guarded by a check) that a property with that name does not exist yet. When you provide your own "console", that check fails.

    If you want to overwrite V8's built-in console, you'll have to create the Context first (via v8::Context::New), then delete (or overwrite) the console property on its global object.

    If all you wanted was to have a console object in your embedder just like the one you know from browsers, then I'm happy to inform you that this work has already been done and you can simply use it :-)