Chromium Code Reviews| 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(); |