gin: Use V8 Maybe APIs

TEST=gin_unittests
BUG=479439

Review URL: https://codereview.chromium.org/1106393002

Cr-Commit-Position: refs/heads/master@{#331923}
diff --git a/gin/arguments.h b/gin/arguments.h
index 4ac38a7..1affa2c 100644
--- a/gin/arguments.h
+++ b/gin/arguments.h
@@ -69,7 +69,10 @@
 
   template<typename T>
   void Return(T val) {
-    info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
+    v8::Local<v8::Value> v8_value;
+    if (!TryConvertToV8(isolate_, val, &v8_value))
+      return;
+    info_->GetReturnValue().Set(v8_value);
   }
 
   v8::Local<v8::Value> PeekNext() const;
diff --git a/gin/converter.cc b/gin/converter.cc
index d870beb..9a3462d 100644
--- a/gin/converter.cc
+++ b/gin/converter.cc
@@ -10,14 +10,30 @@
 using v8::Boolean;
 using v8::External;
 using v8::Function;
+using v8::Int32;
 using v8::Integer;
 using v8::Isolate;
 using v8::Local;
+using v8::Maybe;
+using v8::MaybeLocal;
 using v8::Number;
 using v8::Object;
 using v8::String;
+using v8::Uint32;
 using v8::Value;
 
+namespace {
+
+template <typename T, typename U>
+bool FromMaybe(Maybe<T> maybe, U* out) {
+  if (maybe.IsNothing())
+    return false;
+  *out = static_cast<U>(maybe.FromJust());
+  return true;
+}
+
+}  // namespace
+
 namespace gin {
 
 Local<Value> Converter<bool>::ToV8(Isolate* isolate, bool val) {
@@ -25,8 +41,7 @@
 }
 
 bool Converter<bool>::FromV8(Isolate* isolate, Local<Value> val, bool* out) {
-  *out = val->BooleanValue();
-  return true;
+  return FromMaybe(val->BooleanValue(isolate->GetCurrentContext()), out);
 }
 
 Local<Value> Converter<int32_t>::ToV8(Isolate* isolate, int32_t val) {
@@ -38,7 +53,7 @@
                                 int32_t* out) {
   if (!val->IsInt32())
     return false;
-  *out = val->Int32Value();
+  *out = val.As<Int32>()->Value();
   return true;
 }
 
@@ -51,7 +66,7 @@
                                  uint32_t* out) {
   if (!val->IsUint32())
     return false;
-  *out = val->Uint32Value();
+  *out = val.As<Uint32>()->Value();
   return true;
 }
 
@@ -66,8 +81,7 @@
     return false;
   // Even though IntegerValue returns int64_t, JavaScript cannot represent
   // the full precision of int64_t, which means some rounding might occur.
-  *out = val->IntegerValue();
-  return true;
+  return FromMaybe(val->IntegerValue(isolate->GetCurrentContext()), out);
 }
 
 Local<Value> Converter<uint64_t>::ToV8(Isolate* isolate, uint64_t val) {
@@ -79,8 +93,7 @@
                                  uint64_t* out) {
   if (!val->IsNumber())
     return false;
-  *out = static_cast<uint64_t>(val->IntegerValue());
-  return true;
+  return FromMaybe(val->IntegerValue(isolate->GetCurrentContext()), out);
 }
 
 Local<Value> Converter<float>::ToV8(Isolate* isolate, float val) {
@@ -90,7 +103,7 @@
 bool Converter<float>::FromV8(Isolate* isolate, Local<Value> val, float* out) {
   if (!val->IsNumber())
     return false;
-  *out = static_cast<float>(val->NumberValue());
+  *out = static_cast<float>(val.As<Number>()->Value());
   return true;
 }
 
@@ -103,14 +116,16 @@
                                double* out) {
   if (!val->IsNumber())
     return false;
-  *out = val->NumberValue();
+  *out = val.As<Number>()->Value();
   return true;
 }
 
 Local<Value> Converter<base::StringPiece>::ToV8(Isolate* isolate,
                                                 const base::StringPiece& val) {
-  return String::NewFromUtf8(isolate, val.data(), String::kNormalString,
-                             static_cast<uint32_t>(val.length()));
+  return String::NewFromUtf8(isolate, val.data(),
+                             v8::NewStringType::kNormal,
+                             static_cast<uint32_t>(val.length()))
+      .ToLocalChecked();
 }
 
 Local<Value> Converter<std::string>::ToV8(Isolate* isolate,
@@ -194,10 +209,10 @@
 
 v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
                                       const base::StringPiece& val) {
-  return String::NewFromUtf8(isolate,
-                             val.data(),
-                             String::kInternalizedString,
-                             static_cast<uint32_t>(val.length()));
+  return String::NewFromUtf8(isolate, val.data(),
+                             v8::NewStringType::kInternalized,
+                             static_cast<uint32_t>(val.length()))
+      .ToLocalChecked();
 }
 
 std::string V8ToString(v8::Local<v8::Value> value) {
diff --git a/gin/converter.h b/gin/converter.h
index a07ada7..8d17d41 100644
--- a/gin/converter.h
+++ b/gin/converter.h
@@ -8,12 +8,27 @@
 #include <string>
 #include <vector>
 
+#include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "gin/gin_export.h"
 #include "v8/include/v8.h"
 
 namespace gin {
 
+template<typename KeyType>
+bool SetProperty(v8::Isolate* isolate,
+                 v8::Local<v8::Object> object,
+                 KeyType key,
+                 v8::Local<v8::Value> value) {
+  auto maybe = object->Set(isolate->GetCurrentContext(), key, value);
+  return !maybe.IsNothing() && maybe.FromJust();
+}
+
+template<typename T>
+struct ToV8ReturnsMaybe {
+  static const bool value = false;
+};
+
 template<typename T, typename Enable = void>
 struct Converter {};
 
@@ -84,6 +99,7 @@
 
 template<>
 struct GIN_EXPORT Converter<base::StringPiece> {
+  // This crashes when val.size() > v8::String::kMaxLength.
   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                     const base::StringPiece& val);
   // No conversion out is possible because StringPiece does not contain storage.
@@ -91,6 +107,7 @@
 
 template<>
 struct GIN_EXPORT Converter<std::string> {
+  // This crashes when val.size() > v8::String::kMaxLength.
   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                     const std::string& val);
   static bool FromV8(v8::Isolate* isolate,
@@ -143,12 +160,15 @@
 
 template<typename T>
 struct Converter<std::vector<T> > {
-  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
-                                    const std::vector<T>& val) {
+  static v8::MaybeLocal<v8::Value> ToV8(v8::Local<v8::Context> context,
+                                        const std::vector<T>& val) {
+    v8::Isolate* isolate = context->GetIsolate();
     v8::Local<v8::Array> result(
         v8::Array::New(isolate, static_cast<int>(val.size())));
-    for (size_t i = 0; i < val.size(); ++i) {
-      result->Set(static_cast<int>(i), Converter<T>::ToV8(isolate, val[i]));
+    for (uint32_t i = 0; i < val.size(); ++i) {
+      auto maybe = result->Set(context, i, Converter<T>::ToV8(isolate, val[i]));
+      if (maybe.IsNothing() || !maybe.FromJust())
+        return v8::MaybeLocal<v8::Value>();
     }
     return result;
   }
@@ -163,8 +183,11 @@
     v8::Local<v8::Array> array(v8::Local<v8::Array>::Cast(val));
     uint32_t length = array->Length();
     for (uint32_t i = 0; i < length; ++i) {
+      v8::Local<v8::Value> v8_item;
+      if (!array->Get(isolate->GetCurrentContext(), i).ToLocal(&v8_item))
+        return false;
       T item;
-      if (!Converter<T>::FromV8(isolate, array->Get(i), &item))
+      if (!Converter<T>::FromV8(isolate, v8_item, &item))
         return false;
       result.push_back(item);
     }
@@ -174,18 +197,62 @@
   }
 };
 
+template<typename T>
+struct ToV8ReturnsMaybe<std::vector<T>> {
+  static const bool value = true;
+};
+
 // Convenience functions that deduce T.
 template<typename T>
 v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, T input) {
   return Converter<T>::ToV8(isolate, input);
 }
 
+template<typename T>
+v8::MaybeLocal<v8::Value> ConvertToV8(v8::Local<v8::Context> context, T input) {
+  return Converter<T>::ToV8(context, input);
+}
+
+template<typename T, bool = ToV8ReturnsMaybe<T>::value> struct ToV8Traits;
+
+template <typename T>
+struct ToV8Traits<T, true> {
+  static bool TryConvertToV8(v8::Isolate* isolate,
+                             T input,
+                             v8::Local<v8::Value>* output) {
+    auto maybe = ConvertToV8(isolate->GetCurrentContext(), input);
+    if (maybe.IsEmpty())
+      return false;
+    *output = maybe.ToLocalChecked();
+    return true;
+  }
+};
+
+template <typename T>
+struct ToV8Traits<T, false> {
+  static bool TryConvertToV8(v8::Isolate* isolate,
+                             T input,
+                             v8::Local<v8::Value>* output) {
+    *output = ConvertToV8(isolate, input);
+    return true;
+  }
+};
+
+template <typename T>
+bool TryConvertToV8(v8::Isolate* isolate,
+                    T input,
+                    v8::Local<v8::Value>* output) {
+  return ToV8Traits<T>::TryConvertToV8(isolate, input, output);
+}
+
+// This crashes when input.size() > v8::String::kMaxLength.
 GIN_EXPORT inline v8::Local<v8::String> StringToV8(
     v8::Isolate* isolate,
     const base::StringPiece& input) {
   return ConvertToV8(isolate, input).As<v8::String>();
 }
 
+// This crashes when input.size() > v8::String::kMaxLength.
 GIN_EXPORT v8::Local<v8::String> StringToSymbol(v8::Isolate* isolate,
                                                  const base::StringPiece& val);
 
diff --git a/gin/converter_unittest.cc b/gin/converter_unittest.cc
index 8b9adf4..a7c3547 100644
--- a/gin/converter_unittest.cc
+++ b/gin/converter_unittest.cc
@@ -116,19 +116,16 @@
   expected.push_back(0);
   expected.push_back(1);
 
-  Local<Array> js_array = Local<Array>::Cast(
-      Converter<std::vector<int>>::ToV8(instance_->isolate(), expected));
-  ASSERT_FALSE(js_array.IsEmpty());
-  EXPECT_EQ(3u, js_array->Length());
+  auto maybe = Converter<std::vector<int>>::ToV8(
+      instance_->isolate()->GetCurrentContext(), expected);
+  Local<Value> js_value;
+  EXPECT_TRUE(maybe.ToLocal(&js_value));
+  Local<Array> js_array2 = Local<Array>::Cast(js_value);
+  EXPECT_EQ(3u, js_array2->Length());
   for (size_t i = 0; i < expected.size(); ++i) {
     EXPECT_TRUE(Integer::New(instance_->isolate(), expected[i])
-                    ->StrictEquals(js_array->Get(static_cast<int>(i))));
+                    ->StrictEquals(js_array2->Get(static_cast<int>(i))));
   }
-
-  std::vector<int> actual;
-  EXPECT_TRUE(Converter<std::vector<int> >::FromV8(instance_->isolate(),
-                                                   js_array, &actual));
-  EXPECT_EQ(expected, actual);
 }
 
 }  // namespace gin
diff --git a/gin/dictionary.h b/gin/dictionary.h
index efebfa8..64736b1d 100644
--- a/gin/dictionary.h
+++ b/gin/dictionary.h
@@ -32,13 +32,23 @@
 
   template<typename T>
   bool Get(const std::string& key, T* out) {
-    v8::Local<v8::Value> val = object_->Get(StringToV8(isolate_, key));
+    v8::Local<v8::Value> val;
+    if (!object_->Get(isolate_->GetCurrentContext(), StringToV8(isolate_, key))
+             .ToLocal(&val)) {
+      return false;
+    }
     return ConvertFromV8(isolate_, val, out);
   }
 
   template<typename T>
   bool Set(const std::string& key, T val) {
-    return object_->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val));
+    v8::Local<v8::Value> v8_value;
+    if (!TryConvertToV8(isolate_, val, &v8_value))
+      return false;
+    v8::Maybe<bool> result =
+        object_->Set(isolate_->GetCurrentContext(), StringToV8(isolate_, key),
+                    v8_value);
+    return !result.IsNothing() && result.FromJust();
   }
 
   v8::Isolate* isolate() const { return isolate_; }
diff --git a/gin/interceptor_unittest.cc b/gin/interceptor_unittest.cc
index 01c6ba95..02fb10d 100644
--- a/gin/interceptor_unittest.cc
+++ b/gin/interceptor_unittest.cc
@@ -139,7 +139,7 @@
     v8::Local<v8::String> source = StringToV8(isolate, script_source);
     EXPECT_FALSE(source.IsEmpty());
 
-    gin::TryCatch try_catch;
+    gin::TryCatch try_catch(isolate);
     v8::Local<v8::Script> script = v8::Script::Compile(source);
     EXPECT_FALSE(script.IsEmpty());
     v8::Local<v8::Value> val = script->Run();
diff --git a/gin/modules/console.cc b/gin/modules/console.cc
index d172373..75241df 100644
--- a/gin/modules/console.cc
+++ b/gin/modules/console.cc
@@ -43,7 +43,7 @@
         .Build();
     data->SetObjectTemplate(&g_wrapper_info, templ);
   }
-  return templ->NewInstance();
+  return templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
 }
 
 }  // namespace gin
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
index 6c3e898c..036e98d 100644
--- a/gin/modules/module_registry.cc
+++ b/gin/modules/module_registry.cc
@@ -113,10 +113,14 @@
 }
 
 // static
-void ModuleRegistry::InstallGlobals(v8::Isolate* isolate,
+bool ModuleRegistry::InstallGlobals(v8::Isolate* isolate,
                                     v8::Local<v8::Object> obj) {
-  obj->Set(StringToSymbol(isolate, "define"),
-           GetDefineTemplate(isolate)->GetFunction());
+  v8::Local<v8::Function> function;
+  auto maybe_function =
+      GetDefineTemplate(isolate)->GetFunction(isolate->GetCurrentContext());
+  if (!maybe_function.ToLocal(&function))
+    return false;
+  return SetProperty(isolate, obj, StringToSymbol(isolate, "define"), function);
 }
 
 // static
@@ -177,16 +181,17 @@
   unsatisfied_dependencies_.insert(id);
 }
 
-void ModuleRegistry::RegisterModule(Isolate* isolate,
+bool ModuleRegistry::RegisterModule(Isolate* isolate,
                                     const std::string& id,
                                     v8::Local<Value> module) {
   if (id.empty() || module.IsEmpty())
-    return;
+    return false;
 
+  v8::Local<Object> modules = Local<Object>::New(isolate, modules_);
+  if (!SetProperty(isolate, modules, StringToSymbol(isolate, id), module))
+    return false;
   unsatisfied_dependencies_.erase(id);
   available_modules_.insert(id);
-  v8::Local<Object> modules = Local<Object>::New(isolate, modules_);
-  modules->Set(StringToSymbol(isolate, id), module);
 
   std::pair<LoadModuleCallbackMap::iterator, LoadModuleCallbackMap::iterator>
       range = waiting_callbacks_.equal_range(id);
@@ -203,6 +208,7 @@
     // Should we call the callback asynchronously?
     it->Run(module);
   }
+  return true;
 }
 
 bool ModuleRegistry::CheckDependencies(PendingModule* pending) {
@@ -218,9 +224,9 @@
   return num_missing_dependencies == 0;
 }
 
-void ModuleRegistry::Load(Isolate* isolate, scoped_ptr<PendingModule> pending) {
+bool ModuleRegistry::Load(Isolate* isolate, scoped_ptr<PendingModule> pending) {
   if (!pending->id.empty() && available_modules_.count(pending->id))
-    return;  // We've already loaded this module.
+    return true;  // We've already loaded this module.
 
   uint32_t argc = static_cast<uint32_t>(pending->dependencies.size());
   std::vector<v8::Local<Value> > argv(argc);
@@ -240,7 +246,7 @@
                     &pending->id);
   }
 
-  RegisterModule(isolate, pending->id, module);
+  return RegisterModule(isolate, pending->id, module);
 }
 
 bool ModuleRegistry::AttemptToLoad(Isolate* isolate,
@@ -249,16 +255,15 @@
     pending_modules_.push_back(pending.release());
     return false;
   }
-  Load(isolate, pending.Pass());
-  return true;
+  return Load(isolate, pending.Pass());
 }
 
 v8::Local<v8::Value> ModuleRegistry::GetModule(v8::Isolate* isolate,
                                                 const std::string& id) {
   v8::Local<Object> modules = Local<Object>::New(isolate, modules_);
   v8::Local<String> key = StringToSymbol(isolate, id);
-  DCHECK(modules->HasOwnProperty(key));
-  return modules->Get(key);
+  DCHECK(modules->HasOwnProperty(isolate->GetCurrentContext(), key).FromJust());
+  return modules->Get(isolate->GetCurrentContext(), key).ToLocalChecked();
 }
 
 void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) {
diff --git a/gin/modules/module_registry.h b/gin/modules/module_registry.h
index c53155a..b67387b 100644
--- a/gin/modules/module_registry.h
+++ b/gin/modules/module_registry.h
@@ -47,7 +47,7 @@
 
   // Installs the necessary functions needed for modules.
   // WARNING: this may execute script in the page.
-  static void InstallGlobals(v8::Isolate* isolate, v8::Local<v8::Object> obj);
+  static bool InstallGlobals(v8::Isolate* isolate, v8::Local<v8::Object> obj);
 
   void AddObserver(ModuleRegistryObserver* observer);
   void RemoveObserver(ModuleRegistryObserver* observer);
@@ -81,8 +81,8 @@
 
   explicit ModuleRegistry(v8::Isolate* isolate);
 
-  void Load(v8::Isolate* isolate, scoped_ptr<PendingModule> pending);
-  void RegisterModule(v8::Isolate* isolate,
+  bool Load(v8::Isolate* isolate, scoped_ptr<PendingModule> pending);
+  bool RegisterModule(v8::Isolate* isolate,
                       const std::string& id,
                       v8::Local<v8::Value> module);
 
diff --git a/gin/object_template_builder.cc b/gin/object_template_builder.cc
index 264552f9..28c9791 100644
--- a/gin/object_template_builder.cc
+++ b/gin/object_template_builder.cc
@@ -93,8 +93,11 @@
       NamedInterceptorFromV8(isolate, info.Holder());
   if (!interceptor)
     return;
-  info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(
-      ConvertToV8(isolate, interceptor->EnumerateNamedProperties(isolate))));
+  v8::Local<v8::Value> properties;
+  if (!TryConvertToV8(isolate, interceptor->EnumerateNamedProperties(isolate),
+                      &properties))
+    return;
+  info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(properties));
 }
 
 void IndexedPropertyGetter(uint32_t index,
@@ -126,8 +129,11 @@
       IndexedInterceptorFromV8(isolate, info.Holder());
   if (!interceptor)
     return;
-  info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(
-      ConvertToV8(isolate, interceptor->EnumerateIndexedProperties(isolate))));
+  v8::Local<v8::Value> properties;
+  if (!TryConvertToV8(isolate, interceptor->EnumerateIndexedProperties(isolate),
+                      &properties))
+    return;
+  info.GetReturnValue().Set(v8::Local<v8::Array>::Cast(properties));
 }
 
 }  // namespace
diff --git a/gin/shell/gin_main.cc b/gin/shell/gin_main.cc
index d3bab72..62143c9 100644
--- a/gin/shell/gin_main.cc
+++ b/gin/shell/gin_main.cc
@@ -75,7 +75,9 @@
 
   {
     gin::Runner::Scope scope(&runner);
-    v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+    runner.GetContextHolder()
+        ->isolate()
+        ->SetCaptureStackTraceForUncaughtExceptions(true);
   }
 
   base::CommandLine::StringVector args =
diff --git a/gin/shell_runner.cc b/gin/shell_runner.cc
index eccee9f6..0e534e4 100644
--- a/gin/shell_runner.cc
+++ b/gin/shell_runner.cc
@@ -65,11 +65,13 @@
 
 void ShellRunner::Run(const std::string& source,
                       const std::string& resource_name) {
-  TryCatch try_catch;
   v8::Isolate* isolate = GetContextHolder()->isolate();
-  v8::Local<Script> script = Script::Compile(
-      StringToV8(isolate, source), StringToV8(isolate, resource_name));
-  if (try_catch.HasCaught()) {
+  TryCatch try_catch(isolate);
+  v8::ScriptOrigin origin(StringToV8(isolate, resource_name));
+  auto maybe_script = Script::Compile(GetContextHolder()->context(),
+                                      StringToV8(isolate, source), &origin);
+  v8::Local<Script> script;
+  if (!maybe_script.ToLocal(&script)) {
     delegate_->UnhandledException(this, try_catch);
     return;
   }
@@ -81,13 +83,15 @@
                                         v8::Local<v8::Value> receiver,
                                         int argc,
                                         v8::Local<v8::Value> argv[]) {
-  TryCatch try_catch;
+  TryCatch try_catch(GetContextHolder()->isolate());
   delegate_->WillRunScript(this);
 
-  v8::Local<v8::Value> result = function->Call(receiver, argc, argv);
+  auto maybe_result =
+      function->Call(GetContextHolder()->context(), receiver, argc, argv);
 
   delegate_->DidRunScript(this);
-  if (try_catch.HasCaught())
+  v8::Local<v8::Value> result;
+  if (!maybe_result.ToLocal(&result))
     delegate_->UnhandledException(this, try_catch);
 
   return result;
@@ -98,13 +102,14 @@
 }
 
 void ShellRunner::Run(v8::Local<Script> script) {
-  TryCatch try_catch;
+  TryCatch try_catch(GetContextHolder()->isolate());
   delegate_->WillRunScript(this);
 
-  script->Run();
+  auto maybe = script->Run(GetContextHolder()->context());
 
   delegate_->DidRunScript(this);
-  if (try_catch.HasCaught()) {
+  v8::Local<v8::Value> result;
+  if (!maybe.ToLocal(&result)) {
     delegate_->UnhandledException(this, try_catch);
   }
 }
diff --git a/gin/test/file.cc b/gin/test/file.cc
index adcb341..38efbb4 100644
--- a/gin/test/file.cc
+++ b/gin/test/file.cc
@@ -59,8 +59,10 @@
     names.push_back(name.BaseName().AsUTF8Unsafe());
   }
 
-  return gin::Converter<std::vector<std::string> >::ToV8(args->isolate(),
-                                                         names);
+  v8::Local<v8::Value> v8_names;
+  if (!TryConvertToV8(args->isolate(), names, &v8_names))
+    return v8::Null(args->isolate());
+  return v8_names;
 }
 
 gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
diff --git a/gin/try_catch.cc b/gin/try_catch.cc
index 97e7fe1..df27b9c 100644
--- a/gin/try_catch.cc
+++ b/gin/try_catch.cc
@@ -8,9 +8,21 @@
 
 #include "gin/converter.h"
 
+namespace {
+
+v8::Local<v8::String> GetSourceLine(v8::Isolate* isolate,
+                                    v8::Local<v8::Message> message) {
+  auto maybe = message->GetSourceLine(isolate->GetCurrentContext());
+  v8::Local<v8::String> source_line;
+  return maybe.ToLocal(&source_line) ? source_line : v8::String::Empty(isolate);
+}
+
+}  // namespace
+
 namespace gin {
 
-TryCatch::TryCatch() {
+TryCatch::TryCatch(v8::Isolate* isolate)
+    : isolate_(isolate), try_catch_(isolate) {
 }
 
 TryCatch::~TryCatch() {
@@ -28,7 +40,7 @@
   std::stringstream ss;
   v8::Local<v8::Message> message = try_catch_.Message();
   ss << V8ToString(message->Get()) << std::endl
-     << V8ToString(message->GetSourceLine()) << std::endl;
+     << V8ToString(GetSourceLine(isolate_, message)) << std::endl;
 
   v8::Local<v8::StackTrace> trace = message->GetStackTrace();
   if (trace.IsEmpty())
diff --git a/gin/try_catch.h b/gin/try_catch.h
index 633b909..84b2ae1 100644
--- a/gin/try_catch.h
+++ b/gin/try_catch.h
@@ -16,13 +16,14 @@
 // TryCatch is a convenient wrapper around v8::TryCatch.
 class GIN_EXPORT TryCatch {
  public:
-  TryCatch();
+  explicit TryCatch(v8::Isolate* isolate);
   ~TryCatch();
 
   bool HasCaught();
   std::string GetStackTrace();
 
  private:
+  v8::Isolate* isolate_;
   v8::TryCatch try_catch_;
 
   DISALLOW_COPY_AND_ASSIGN(TryCatch);
diff --git a/gin/wrappable.cc b/gin/wrappable.cc
index 09c17a3..27c58df 100644
--- a/gin/wrappable.cc
+++ b/gin/wrappable.cc
@@ -49,10 +49,10 @@
     data->SetObjectTemplate(info, templ);
   }
   CHECK_EQ(kNumberOfInternalFields, templ->InternalFieldCount());
-  v8::Local<v8::Object> wrapper = templ->NewInstance();
+  v8::Local<v8::Object> wrapper;
   // |wrapper| may be empty in some extreme cases, e.g., when
   // Object.prototype.constructor is overwritten.
-  if (wrapper.IsEmpty()) {
+  if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) {
     // The current wrappable object will be no longer managed by V8. Delete this
     // now.
     delete this;
diff --git a/gin/wrappable_unittest.cc b/gin/wrappable_unittest.cc
index 3d795716..70cb224 100644
--- a/gin/wrappable_unittest.cc
+++ b/gin/wrappable_unittest.cc
@@ -183,7 +183,7 @@
       "   else obj.value = 191; })");
   EXPECT_FALSE(source.IsEmpty());
 
-  gin::TryCatch try_catch;
+  gin::TryCatch try_catch(isolate);
   v8::Local<v8::Script> script = v8::Script::Compile(source);
   EXPECT_FALSE(script.IsEmpty());
   v8::Local<v8::Value> val = script->Run();
@@ -209,7 +209,7 @@
                                              "(function(obj) {"
                                              "obj.sayHello('Lily');"
                                              "})");
-  gin::TryCatch try_catch;
+  gin::TryCatch try_catch(isolate);
   v8::Local<v8::Script> script = v8::Script::Compile(source);
   v8::Local<v8::Value> val = script->Run();
   v8::Local<v8::Function> func;
@@ -232,7 +232,7 @@
                                              "(function(obj) {"
                                              "obj(42, 2, 5);"
                                              "})");
-  gin::TryCatch try_catch;
+  gin::TryCatch try_catch(isolate);
   v8::Local<v8::Script> script = v8::Script::Compile(source);
   v8::Local<v8::Value> val = script->Run();
   v8::Local<v8::Function> func;
@@ -255,7 +255,7 @@
                                              "(function(obj) {"
                                              "new obj(42, 2, 5);"
                                              "})");
-  gin::TryCatch try_catch;
+  gin::TryCatch try_catch(isolate);
   v8::Local<v8::Script> script = v8::Script::Compile(source);
   v8::Local<v8::Value> val = script->Run();
   v8::Local<v8::Function> func;