Index: chrome/renderer/extensions/module_system.cc |
diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc |
index 26590475d0bd1ac967a6575f209eab5e1b4e7367..0eaa0cca53c8bb97510f3aa515579e439c08af7e 100644 |
--- a/chrome/renderer/extensions/module_system.cc |
+++ b/chrome/renderer/extensions/module_system.cc |
@@ -6,6 +6,10 @@ |
#include "base/bind.h" |
#include "base/stl_util.h" |
+#include "base/stringprintf.h" |
+#include "chrome/common/extensions/extension_messages.h" |
+#include "chrome/renderer/extensions/chrome_v8_context.h" |
+#include "content/public/renderer/render_view.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h" |
namespace { |
@@ -21,15 +25,15 @@ namespace extensions { |
ModuleSystem::ModuleSystem(v8::Handle<v8::Context> context, |
SourceMap* source_map) |
- : NativeHandler(context->GetIsolate()), |
- context_(v8::Persistent<v8::Context>::New(context->GetIsolate(), |
- context)), |
+ : ObjectBackedNativeHandler(context->GetIsolate()), |
+ context_(context), |
source_map_(source_map), |
- natives_enabled_(0) { |
+ natives_enabled_(0), |
+ is_valid_(true) { |
RouteFunction("require", |
base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
RouteFunction("requireNative", |
- base::Bind(&ModuleSystem::GetNative, base::Unretained(this))); |
+ base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); |
v8::Handle<v8::Object> global(context_->Global()); |
global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); |
@@ -38,11 +42,19 @@ ModuleSystem::ModuleSystem(v8::Handle<v8::Context> context, |
} |
ModuleSystem::~ModuleSystem() { |
+ Invalidate(); |
+} |
+ |
+void ModuleSystem::Invalidate() { |
+ if (!is_valid_) |
+ return; |
+ |
v8::HandleScope handle_scope; |
+ is_valid_ = false; |
not at google - send to devlin
2013/02/20 00:36:38
I can't get over the weird placement of this line
cduvall
2013/02/20 00:57:53
Done.
|
// Deleting this value here prevents future lazy field accesses from |
// referencing ModuleSystem after it has been freed. |
- context_->Global()->DeleteHiddenValue(v8::String::New(kModuleSystem)); |
- context_.Dispose(context_->GetIsolate()); |
+ context_->Global()->DeleteHiddenValue( |
+ v8::String::New(kModuleSystem)); |
} |
ModuleSystem::NativesEnabledScope::NativesEnabledScope( |
@@ -73,13 +85,10 @@ void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { |
} |
// static |
-void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { |
- v8::HandleScope handle_scope; |
- |
+std::string ModuleSystem::CreateExceptionString(const v8::TryCatch& try_catch) { |
v8::Handle<v8::Message> message(try_catch.Message()); |
if (message.IsEmpty()) { |
- LOG(ERROR) << "try_catch has no message"; |
- return; |
+ return "try_catch has no message"; |
} |
std::string resource_name = "<unknown resource>"; |
@@ -92,6 +101,16 @@ void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { |
if (!message->Get().IsEmpty()) |
error_message = *v8::String::Utf8Value(message->Get()); |
+ return base::StringPrintf("[%s(%d)]%s", |
not at google - send to devlin
2013/02/20 00:36:38
This is supposed to say like
[foo(10)]Cannot acce
cduvall
2013/02/20 00:57:53
I just had it like this because thats how it was b
|
+ resource_name.c_str(), |
+ message->GetLineNumber(), |
+ error_message.c_str()); |
+} |
+ |
+// static |
+void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { |
+ v8::HandleScope handle_scope; |
+ |
std::string stack_trace = "<stack trace unavailable>"; |
if (!try_catch.StackTrace().IsEmpty()) { |
v8::String::Utf8Value stack_value(try_catch.StackTrace()); |
@@ -101,14 +120,13 @@ void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { |
stack_trace = "<could not convert stack trace to string>"; |
} |
- LOG(ERROR) << "[" << resource_name << "(" << message->GetLineNumber() << ")] " |
- << error_message |
- << "{" << stack_trace << "}"; |
+ LOG(ERROR) << CreateExceptionString(try_catch) << "{" << stack_trace << "}"; |
} |
-void ModuleSystem::Require(const std::string& module_name) { |
+v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { |
v8::HandleScope handle_scope; |
- RequireForJsInner(v8::String::New(module_name.c_str())); |
+ return handle_scope.Close( |
+ RequireForJsInner(v8::String::New(module_name.c_str()))); |
} |
v8::Handle<v8::Value> ModuleSystem::RequireForJs(const v8::Arguments& args) { |
@@ -120,7 +138,9 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJs(const v8::Arguments& args) { |
v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( |
v8::Handle<v8::String> module_name) { |
v8::HandleScope handle_scope; |
- v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); |
+ if (!is_valid_) |
not at google - send to devlin
2013/02/20 00:36:38
This shouldn't be possible, though, of course, if
cduvall
2013/02/20 00:57:53
Done.
|
+ return handle_scope.Close(v8::Undefined()); |
+ v8::Handle<v8::Object> global(context_->Global()); |
v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast( |
global->GetHiddenValue(v8::String::New(kModulesField)))); |
v8::Handle<v8::Value> exports(modules->Get(module_name)); |
@@ -160,10 +180,11 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( |
return handle_scope.Close(exports); |
} |
-void ModuleSystem::CallModuleMethod(const std::string& module_name, |
- const std::string& method_name) { |
+v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
+ const std::string& module_name, |
+ const std::string& method_name) { |
std::vector<v8::Handle<v8::Value> > args; |
- CallModuleMethod(module_name, method_name, &args); |
+ return CallModuleMethod(module_name, method_name, &args); |
} |
v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
@@ -183,8 +204,7 @@ v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
return v8::Local<v8::Value>(); |
v8::Handle<v8::Function> func = |
v8::Handle<v8::Function>::Cast(value); |
- // TODO(jeremya/koz): refer to context_ here, not the current context. |
- v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); |
+ v8::Handle<v8::Object> global(context_->Global()); |
v8::Local<v8::Value> result; |
{ |
WebKit::WebScopedMicrotaskSuppression suppression; |
@@ -197,6 +217,10 @@ v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
return handle_scope.Close(result); |
} |
+bool ModuleSystem::HasNativeHandler(const std::string& name) { |
+ return native_handler_map_.find(name) != native_handler_map_.end(); |
+} |
+ |
void ModuleSystem::RegisterNativeHandler(const std::string& name, |
scoped_ptr<NativeHandler> native_handler) { |
native_handler_map_[name] = |
@@ -213,13 +237,29 @@ void ModuleSystem::RunString(const std::string& code, const std::string& name) { |
} |
// static |
+v8::Handle<v8::Value> ModuleSystem::NativeLazyFieldGetter( |
+ v8::Local<v8::String> property, const v8::AccessorInfo& info) { |
+ return LazyFieldGetterInner(property, |
+ info, |
+ &ModuleSystem::RequireNativeFromString); |
+} |
+ |
+// static |
v8::Handle<v8::Value> ModuleSystem::LazyFieldGetter( |
v8::Local<v8::String> property, const v8::AccessorInfo& info) { |
+ return LazyFieldGetterInner(property, info, &ModuleSystem::Require); |
+} |
+ |
+// static |
+v8::Handle<v8::Value> ModuleSystem::LazyFieldGetterInner( |
+ v8::Local<v8::String> property, |
+ const v8::AccessorInfo& info, |
+ GetModuleFunc get_module) { |
CHECK(!info.Data().IsEmpty()); |
CHECK(info.Data()->IsObject()); |
v8::HandleScope handle_scope; |
v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); |
- v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); |
+ v8::Handle<v8::Object> global(parameters->CreationContext()->Global()); |
v8::Handle<v8::Value> module_system_value = |
global->GetHiddenValue(v8::String::New(kModuleSystem)); |
if (module_system_value->IsUndefined()) { |
@@ -229,38 +269,61 @@ v8::Handle<v8::Value> ModuleSystem::LazyFieldGetter( |
ModuleSystem* module_system = static_cast<ModuleSystem*>( |
v8::Handle<v8::External>::Cast(module_system_value)->Value()); |
- v8::Handle<v8::Object> module; |
- { |
- NativesEnabledScope scope(module_system); |
- module = v8::Handle<v8::Object>::Cast(module_system->RequireForJsInner( |
- parameters->Get(v8::String::New(kModuleName))->ToString())); |
+ std::string name = *v8::String::AsciiValue( |
+ parameters->Get(v8::String::New(kModuleName))->ToString()); |
+ |
+ NativesEnabledScope scope(module_system); |
+ v8::TryCatch try_catch; |
+ v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast( |
+ (module_system->*get_module)(name)); |
+ if (try_catch.HasCaught()) { |
+ module_system->HandleException(try_catch); |
+ return handle_scope.Close(v8::Handle<v8::Value>()); |
} |
+ |
if (module.IsEmpty()) |
return handle_scope.Close(v8::Handle<v8::Value>()); |
v8::Handle<v8::String> field = |
parameters->Get(v8::String::New(kModuleField))->ToString(); |
- return handle_scope.Close(module->Get(field)); |
+ v8::Local<v8::Value> new_field = module->Get(field); |
+ return handle_scope.Close(new_field); |
} |
void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, |
const std::string& field, |
const std::string& module_name, |
const std::string& module_field) { |
+ SetLazyField(object, field, module_name, module_field, |
+ &ModuleSystem::LazyFieldGetter); |
+} |
+ |
+void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, |
+ const std::string& field, |
+ const std::string& module_name, |
+ const std::string& module_field, |
+ v8::AccessorGetter getter) { |
v8::HandleScope handle_scope; |
v8::Handle<v8::Object> parameters = v8::Object::New(); |
parameters->Set(v8::String::New(kModuleName), |
v8::String::New(module_name.c_str())); |
parameters->Set(v8::String::New(kModuleField), |
v8::String::New(module_field.c_str())); |
- |
object->SetAccessor(v8::String::New(field.c_str()), |
- &ModuleSystem::LazyFieldGetter, |
+ getter, |
NULL, |
parameters); |
} |
+void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, |
+ const std::string& field, |
+ const std::string& module_name, |
+ const std::string& module_field) { |
+ SetLazyField(object, field, module_name, module_field, |
+ &ModuleSystem::NativeLazyFieldGetter); |
+} |
+ |
v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, |
v8::Handle<v8::String> name) { |
v8::HandleScope handle_scope; |
@@ -290,13 +353,18 @@ v8::Handle<v8::Value> ModuleSystem::GetSource( |
return handle_scope.Close(source_map_->GetSource(module_name)); |
} |
-v8::Handle<v8::Value> ModuleSystem::GetNative(const v8::Arguments& args) { |
+v8::Handle<v8::Value> ModuleSystem::RequireNative(const v8::Arguments& args) { |
CHECK_EQ(1, args.Length()); |
+ std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); |
+ return RequireNativeFromString(native_name); |
+} |
+ |
+v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( |
+ const std::string& native_name) { |
if (natives_enabled_ == 0) |
return ThrowException("Natives disabled"); |
- std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); |
if (overridden_native_handlers_.count(native_name) > 0u) |
- return RequireForJs(args); |
+ return RequireForJsInner(v8::String::New(native_name.c_str())); |
NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
if (i == native_handler_map_.end()) |
return v8::Undefined(); |