Search code examples
javascriptc++embeddingv8

Why does creating new v8::Array before v8::Scope cause segmentation fault, but v8::String and v8::FunctionTemplate do not?


Please consider the following code snippets, based on v8's sample.cc sample shell, which causes a segmentation fault:

int RunMain(int argc, char* argv[]) {

  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::HandleScope handle_scope;
  // Create a template for the global object.
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

    v8::Handle<v8::String> testStr = v8::String::New("test");

    v8::Handle<v8::Array> testArr = v8::Array::New();

  // Create a new execution environment containing the built-in
  // functions
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
  // Enter the newly created execution environment.
  v8::Context::Scope context_scope(context);

  return 0;
}

int main(int argc, char* argv[]) {
  int result = RunMain(argc, argv);
  v8::V8::Dispose();
  return result;
}

However, if I instantiate the v8::Array after the v8::Context is instantiated and the scope is set, then the code does not segfault:

int RunMain(int argc, char* argv[]) {

  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::HandleScope handle_scope;
  // Create a template for the global object.
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

    v8::Handle<v8::String> testStr = v8::String::New("test");


  // Create a new execution environment containing the built-in
  // functions
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
  // Enter the newly created execution environment.
  v8::Context::Scope context_scope(context);

  v8::Handle<v8::Array> testArr = v8::Array::New();

  return 0;
}

int main(int argc, char* argv[]) {
  int result = RunMain(argc, argv);
  v8::V8::Dispose();
  return result;
}

My question is: why does instantiating the v8::Array in the first example cause the application to segfault, whereas creating the v8::Array after the v8::Context is created does not cause the application to segfault? And, why does instantiating a v8::String before the Context is created also not cause the application to segfault?

This question is relevant, because in a real shell application, I would like to instantiate an array and assign it to the global context object, but this is not possible, as it seems the context must be created before the v8::Array can be instantiated, thus creating a cyclic dependency.

I'd appreciate any guidance anyone can provide.


Solution

  • When you create a new v8::Array via API V8 actually invokes Array constructor from the current context. It's almost as if you executed new Array(n) in JavaScript. If there is no context then there is nothing V8 can invoke to create an array thats why it segfaults.

    v8::String represents primitive string value. No context specific constructors have to be invoked to create it. That's why you can create it before context without segfaulting V8.

    You can extend context's global object after it was created by directly setting fields on the object returned by Context::Global() method.