Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/extensions/module_system.h" | 5 #include "extensions/renderer/module_system.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "chrome/common/chrome_switches.h" | |
| 14 #include "chrome/common/extensions/features/feature_channel.h" | 13 #include "chrome/common/extensions/features/feature_channel.h" |
| 15 #include "chrome/renderer/extensions/chrome_v8_context.h" | |
| 16 #include "chrome/renderer/extensions/console.h" | |
| 17 #include "chrome/renderer/extensions/safe_builtins.h" | |
| 18 #include "content/public/renderer/render_view.h" | 14 #include "content/public/renderer/render_view.h" |
| 19 #include "extensions/common/extension_messages.h" | 15 #include "extensions/common/extension_messages.h" |
| 16 #include "extensions/renderer/console.h" | |
| 17 #include "extensions/renderer/safe_builtins.h" | |
| 18 #include "extensions/renderer/script_context.h" | |
| 20 #include "third_party/WebKit/public/web/WebFrame.h" | 19 #include "third_party/WebKit/public/web/WebFrame.h" |
| 21 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" | 20 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" |
| 22 | 21 |
| 23 namespace extensions { | 22 namespace extensions { |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 const char* kModuleSystem = "module_system"; | 26 const char* kModuleSystem = "module_system"; |
| 28 const char* kModuleName = "module_name"; | 27 const char* kModuleName = "module_name"; |
| 29 const char* kModuleField = "module_field"; | 28 const char* kModuleField = "module_field"; |
| 30 const char* kModulesField = "modules"; | 29 const char* kModulesField = "modules"; |
| 31 | 30 |
| 32 // Logs a fatal error for the calling context, with some added metadata about | 31 // Logs a fatal error for the calling context, with some added metadata about |
| 33 // the context: | 32 // the context: |
| 34 // - Its type (blessed, unblessed, etc). | 33 // - Its type (blessed, unblessed, etc). |
| 35 // - Whether it's valid. | 34 // - Whether it's valid. |
| 36 // - The extension ID, if one exists. | 35 // - The extension ID, if one exists. |
| 37 // | 36 // |
| 38 // This will only actual be fatal in in dev/canary, since in too many cases | 37 // This will only actual be fatal in in dev/canary, since in too many cases |
| 39 // we're at the mercy of the extension or web page's environment. They can mess | 38 // we're at the mercy of the extension or web page's environment. They can mess |
| 40 // up our JS in unexpected ways. Hopefully dev/canary channel will pick up such | 39 // up our JS in unexpected ways. Hopefully dev/canary channel will pick up such |
| 41 // problems, but given the wider variety on stable/beta it's impossible to know. | 40 // problems, but given the wider variety on stable/beta it's impossible to know. |
| 42 void Fatal(ChromeV8Context* context, const std::string& message) { | 41 void Fatal(ScriptContext* context, const std::string& message) { |
| 43 // Prepend some context metadata. | 42 // Prepend some context metadata. |
| 44 std::string full_message = "("; | 43 std::string full_message = "("; |
| 45 if (!context->is_valid()) | 44 if (!context->is_valid()) |
| 46 full_message += "Invalid "; | 45 full_message += "Invalid "; |
| 47 full_message += context->GetContextTypeDescription(); | 46 full_message += context->GetContextTypeDescription(); |
| 48 full_message += " context"; | 47 full_message += " context"; |
| 49 if (context->extension()) { | 48 if (context->extension()) { |
| 50 full_message += " for "; | 49 full_message += " for "; |
| 51 full_message += context->extension()->id(); | 50 full_message += context->extension()->id(); |
| 52 } | 51 } |
| 53 full_message += ") "; | 52 full_message += ") "; |
| 54 full_message += message; | 53 full_message += message; |
| 55 | 54 |
| 56 // <= dev means dev, canary, and trunk. | 55 // <= dev means dev, canary, and trunk. |
| 57 if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV) | 56 if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV) |
|
not at google - send to devlin
2014/04/11 15:38:55
you could abstract away this decision somewhere ea
Ken Rockot(use gerrit already)
2014/04/11 17:02:18
Yep, that's the plan
| |
| 58 console::Fatal(context->isolate()->GetCallingContext(), full_message); | 57 console::Fatal(context->isolate()->GetCallingContext(), full_message); |
| 59 else | 58 else |
| 60 console::Error(context->isolate()->GetCallingContext(), full_message); | 59 console::Error(context->isolate()->GetCallingContext(), full_message); |
| 61 } | 60 } |
| 62 | 61 |
| 63 void Warn(v8::Isolate* isolate, const std::string& message) { | 62 void Warn(v8::Isolate* isolate, const std::string& message) { |
| 64 console::Warn(isolate->GetCallingContext(), message); | 63 console::Warn(isolate->GetCallingContext(), message); |
| 65 } | 64 } |
| 66 | 65 |
| 67 // Default exception handler which logs the exception. | 66 // Default exception handler which logs the exception. |
| 68 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { | 67 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { |
| 69 public: | 68 public: |
| 70 explicit DefaultExceptionHandler(ChromeV8Context* context) | 69 explicit DefaultExceptionHandler(ScriptContext* context) |
| 71 : context_(context) {} | 70 : context_(context) {} |
| 72 | 71 |
| 73 // Fatally dumps the debug info from |try_catch| to the console. | 72 // Fatally dumps the debug info from |try_catch| to the console. |
| 74 // Make sure this is never used for exceptions that originate in external | 73 // Make sure this is never used for exceptions that originate in external |
| 75 // code! | 74 // code! |
| 76 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { | 75 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { |
| 77 v8::HandleScope handle_scope(context_->isolate()); | 76 v8::HandleScope handle_scope(context_->isolate()); |
| 78 std::string stack_trace = "<stack trace unavailable>"; | 77 std::string stack_trace = "<stack trace unavailable>"; |
| 79 if (!try_catch.StackTrace().IsEmpty()) { | 78 if (!try_catch.StackTrace().IsEmpty()) { |
| 80 v8::String::Utf8Value stack_value(try_catch.StackTrace()); | 79 v8::String::Utf8Value stack_value(try_catch.StackTrace()); |
| 81 if (*stack_value) | 80 if (*stack_value) |
| 82 stack_trace.assign(*stack_value, stack_value.length()); | 81 stack_trace.assign(*stack_value, stack_value.length()); |
| 83 else | 82 else |
| 84 stack_trace = "<could not convert stack trace to string>"; | 83 stack_trace = "<could not convert stack trace to string>"; |
| 85 } | 84 } |
| 86 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}"); | 85 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}"); |
| 87 } | 86 } |
| 88 | 87 |
| 89 private: | 88 private: |
| 90 ChromeV8Context* context_; | 89 ScriptContext* context_; |
| 91 }; | 90 }; |
| 92 | 91 |
| 93 } // namespace | 92 } // namespace |
| 94 | 93 |
| 95 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( | 94 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( |
| 96 const v8::TryCatch& try_catch) { | 95 const v8::TryCatch& try_catch) { |
| 97 v8::Handle<v8::Message> message(try_catch.Message()); | 96 v8::Handle<v8::Message> message(try_catch.Message()); |
| 98 if (message.IsEmpty()) { | 97 if (message.IsEmpty()) { |
| 99 return "try_catch has no message"; | 98 return "try_catch has no message"; |
| 100 } | 99 } |
| 101 | 100 |
| 102 std::string resource_name = "<unknown resource>"; | 101 std::string resource_name = "<unknown resource>"; |
| 103 if (!message->GetScriptResourceName().IsEmpty()) { | 102 if (!message->GetScriptResourceName().IsEmpty()) { |
| 104 v8::String::Utf8Value resource_name_v8( | 103 v8::String::Utf8Value resource_name_v8( |
| 105 message->GetScriptResourceName()->ToString()); | 104 message->GetScriptResourceName()->ToString()); |
| 106 resource_name.assign(*resource_name_v8, resource_name_v8.length()); | 105 resource_name.assign(*resource_name_v8, resource_name_v8.length()); |
| 107 } | 106 } |
| 108 | 107 |
| 109 std::string error_message = "<no error message>"; | 108 std::string error_message = "<no error message>"; |
| 110 if (!message->Get().IsEmpty()) { | 109 if (!message->Get().IsEmpty()) { |
| 111 v8::String::Utf8Value error_message_v8(message->Get()); | 110 v8::String::Utf8Value error_message_v8(message->Get()); |
| 112 error_message.assign(*error_message_v8, error_message_v8.length()); | 111 error_message.assign(*error_message_v8, error_message_v8.length()); |
| 113 } | 112 } |
| 114 | 113 |
| 115 return base::StringPrintf("%s:%d: %s", | 114 return base::StringPrintf("%s:%d: %s", |
| 116 resource_name.c_str(), | 115 resource_name.c_str(), |
| 117 message->GetLineNumber(), | 116 message->GetLineNumber(), |
| 118 error_message.c_str()); | 117 error_message.c_str()); |
| 119 } | 118 } |
| 120 | 119 |
| 121 ModuleSystem::ModuleSystem(ChromeV8Context* context, SourceMap* source_map) | 120 ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map) |
| 122 : ObjectBackedNativeHandler(context), | 121 : ObjectBackedNativeHandler(context), |
| 123 context_(context), | 122 context_(context), |
| 124 source_map_(source_map), | 123 source_map_(source_map), |
| 125 natives_enabled_(0), | 124 natives_enabled_(0), |
| 126 exception_handler_(new DefaultExceptionHandler(context)) { | 125 exception_handler_(new DefaultExceptionHandler(context)) { |
| 127 RouteFunction("require", | 126 RouteFunction( |
| 127 "require", | |
| 128 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 128 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
| 129 RouteFunction("requireNative", | 129 RouteFunction( |
| 130 "requireNative", | |
| 130 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); | 131 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); |
| 131 RouteFunction("privates", | 132 RouteFunction("privates", |
| 132 base::Bind(&ModuleSystem::Private, base::Unretained(this))); | 133 base::Bind(&ModuleSystem::Private, base::Unretained(this))); |
| 133 | 134 |
| 134 v8::Handle<v8::Object> global(context->v8_context()->Global()); | 135 v8::Handle<v8::Object> global(context->v8_context()->Global()); |
| 135 v8::Isolate* isolate = context->isolate(); | 136 v8::Isolate* isolate = context->isolate(); |
| 136 global->SetHiddenValue( | 137 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModulesField), |
| 137 v8::String::NewFromUtf8(isolate, kModulesField), | 138 v8::Object::New(isolate)); |
| 138 v8::Object::New(isolate)); | 139 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), |
| 139 global->SetHiddenValue( | 140 v8::External::New(isolate, this)); |
| 140 v8::String::NewFromUtf8(isolate, kModuleSystem), | |
| 141 v8::External::New(isolate, this)); | |
| 142 } | 141 } |
| 143 | 142 |
| 144 ModuleSystem::~ModuleSystem() { | 143 ModuleSystem::~ModuleSystem() { Invalidate(); } |
| 145 Invalidate(); | |
| 146 } | |
| 147 | 144 |
| 148 void ModuleSystem::Invalidate() { | 145 void ModuleSystem::Invalidate() { |
| 149 if (!is_valid()) | 146 if (!is_valid()) |
| 150 return; | 147 return; |
| 151 | 148 |
| 152 // Clear the module system properties from the global context. It's polite, | 149 // Clear the module system properties from the global context. It's polite, |
| 153 // and we use this as a signal in lazy handlers that we no longer exist. | 150 // and we use this as a signal in lazy handlers that we no longer exist. |
| 154 { | 151 { |
| 155 v8::HandleScope scope(GetIsolate()); | 152 v8::HandleScope scope(GetIsolate()); |
| 156 v8::Handle<v8::Object> global = context()->v8_context()->Global(); | 153 v8::Handle<v8::Object> global = context()->v8_context()->Global(); |
| 157 global->DeleteHiddenValue( | 154 global->DeleteHiddenValue( |
| 158 v8::String::NewFromUtf8(GetIsolate(), kModulesField)); | 155 v8::String::NewFromUtf8(GetIsolate(), kModulesField)); |
| 159 global->DeleteHiddenValue( | 156 global->DeleteHiddenValue( |
| 160 v8::String::NewFromUtf8(GetIsolate(), kModuleSystem)); | 157 v8::String::NewFromUtf8(GetIsolate(), kModuleSystem)); |
| 161 } | 158 } |
| 162 | 159 |
| 163 // Invalidate all of the successfully required handlers we own. | 160 // Invalidate all of the successfully required handlers we own. |
| 164 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); | 161 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); |
| 165 it != native_handler_map_.end(); ++it) { | 162 it != native_handler_map_.end(); |
| 163 ++it) { | |
| 166 it->second->Invalidate(); | 164 it->second->Invalidate(); |
| 167 } | 165 } |
| 168 | 166 |
| 169 ObjectBackedNativeHandler::Invalidate(); | 167 ObjectBackedNativeHandler::Invalidate(); |
| 170 } | 168 } |
| 171 | 169 |
| 172 ModuleSystem::NativesEnabledScope::NativesEnabledScope( | 170 ModuleSystem::NativesEnabledScope::NativesEnabledScope( |
| 173 ModuleSystem* module_system) | 171 ModuleSystem* module_system) |
| 174 : module_system_(module_system) { | 172 : module_system_(module_system) { |
| 175 module_system_->natives_enabled_++; | 173 module_system_->natives_enabled_++; |
| 176 } | 174 } |
| 177 | 175 |
| 178 ModuleSystem::NativesEnabledScope::~NativesEnabledScope() { | 176 ModuleSystem::NativesEnabledScope::~NativesEnabledScope() { |
| 179 module_system_->natives_enabled_--; | 177 module_system_->natives_enabled_--; |
| 180 CHECK_GE(module_system_->natives_enabled_, 0); | 178 CHECK_GE(module_system_->natives_enabled_, 0); |
| 181 } | 179 } |
| 182 | 180 |
| 183 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { | 181 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { |
| 184 exception_handler_->HandleUncaughtException(try_catch); | 182 exception_handler_->HandleUncaughtException(try_catch); |
| 185 } | 183 } |
| 186 | 184 |
| 187 v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { | 185 v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { |
| 188 v8::EscapableHandleScope handle_scope(GetIsolate()); | 186 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 189 return handle_scope.Escape(RequireForJsInner( | 187 return handle_scope.Escape(RequireForJsInner( |
| 190 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str()))); | 188 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str()))); |
| 191 } | 189 } |
| 192 | 190 |
| 193 void ModuleSystem::RequireForJs( | 191 void ModuleSystem::RequireForJs( |
| 194 const v8::FunctionCallbackInfo<v8::Value>& args) { | 192 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 195 v8::Handle<v8::String> module_name = args[0]->ToString(); | 193 v8::Handle<v8::String> module_name = args[0]->ToString(); |
| 196 args.GetReturnValue().Set(RequireForJsInner(module_name)); | 194 args.GetReturnValue().Set(RequireForJsInner(module_name)); |
| 197 } | 195 } |
| 198 | 196 |
| 199 v8::Local<v8::Value> ModuleSystem::RequireForJsInner( | 197 v8::Local<v8::Value> ModuleSystem::RequireForJsInner( |
| 200 v8::Handle<v8::String> module_name) { | 198 v8::Handle<v8::String> module_name) { |
| 201 v8::EscapableHandleScope handle_scope(GetIsolate()); | 199 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 202 v8::Context::Scope context_scope(context()->v8_context()); | 200 v8::Context::Scope context_scope(context()->v8_context()); |
| 203 | 201 |
| 204 v8::Handle<v8::Object> global(context()->v8_context()->Global()); | 202 v8::Handle<v8::Object> global(context()->v8_context()->Global()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 217 v8::Local<v8::Value> exports(modules->Get(module_name)); | 215 v8::Local<v8::Value> exports(modules->Get(module_name)); |
| 218 if (!exports->IsUndefined()) | 216 if (!exports->IsUndefined()) |
| 219 return handle_scope.Escape(exports); | 217 return handle_scope.Escape(exports); |
| 220 | 218 |
| 221 std::string module_name_str = *v8::String::Utf8Value(module_name); | 219 std::string module_name_str = *v8::String::Utf8Value(module_name); |
| 222 v8::Handle<v8::Value> source(GetSource(module_name_str)); | 220 v8::Handle<v8::Value> source(GetSource(module_name_str)); |
| 223 if (source.IsEmpty() || source->IsUndefined()) { | 221 if (source.IsEmpty() || source->IsUndefined()) { |
| 224 Fatal(context_, "No source for require(" + module_name_str + ")"); | 222 Fatal(context_, "No source for require(" + module_name_str + ")"); |
| 225 return v8::Undefined(GetIsolate()); | 223 return v8::Undefined(GetIsolate()); |
| 226 } | 224 } |
| 227 v8::Handle<v8::String> wrapped_source(WrapSource( | 225 v8::Handle<v8::String> wrapped_source( |
| 228 v8::Handle<v8::String>::Cast(source))); | 226 WrapSource(v8::Handle<v8::String>::Cast(source))); |
| 229 // Modules are wrapped in (function(){...}) so they always return functions. | 227 // Modules are wrapped in (function(){...}) so they always return functions. |
| 230 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); | 228 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); |
| 231 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 229 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { |
| 232 Fatal(context_, "Bad source for require(" + module_name_str + ")"); | 230 Fatal(context_, "Bad source for require(" + module_name_str + ")"); |
| 233 return v8::Undefined(GetIsolate()); | 231 return v8::Undefined(GetIsolate()); |
| 234 } | 232 } |
| 235 | 233 |
| 236 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 234 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); |
| 237 | 235 |
| 238 exports = v8::Object::New(GetIsolate()); | 236 exports = v8::Object::New(GetIsolate()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 std::vector<v8::Handle<v8::Value> >* args) { | 283 std::vector<v8::Handle<v8::Value> >* args) { |
| 286 return CallModuleMethod( | 284 return CallModuleMethod( |
| 287 module_name, method_name, args->size(), vector_as_array(args)); | 285 module_name, method_name, args->size(), vector_as_array(args)); |
| 288 } | 286 } |
| 289 | 287 |
| 290 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( | 288 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
| 291 const std::string& module_name, | 289 const std::string& module_name, |
| 292 const std::string& method_name, | 290 const std::string& method_name, |
| 293 int argc, | 291 int argc, |
| 294 v8::Handle<v8::Value> argv[]) { | 292 v8::Handle<v8::Value> argv[]) { |
| 295 TRACE_EVENT2("v8", "v8.callModuleMethod", | 293 TRACE_EVENT2("v8", |
| 296 "module_name", module_name, | 294 "v8.callModuleMethod", |
| 297 "method_name", method_name); | 295 "module_name", |
| 296 module_name, | |
| 297 "method_name", | |
| 298 method_name); | |
| 298 | 299 |
| 299 v8::EscapableHandleScope handle_scope(GetIsolate()); | 300 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 300 v8::Context::Scope context_scope(context()->v8_context()); | 301 v8::Context::Scope context_scope(context()->v8_context()); |
| 301 | 302 |
| 302 v8::Local<v8::Value> module; | 303 v8::Local<v8::Value> module; |
| 303 { | 304 { |
| 304 NativesEnabledScope natives_enabled(this); | 305 NativesEnabledScope natives_enabled(this); |
| 305 module = RequireForJsInner( | 306 module = RequireForJsInner( |
| 306 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); | 307 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); |
| 307 } | 308 } |
| 308 | 309 |
| 309 if (module.IsEmpty() || !module->IsObject()) { | 310 if (module.IsEmpty() || !module->IsObject()) { |
| 310 Fatal(context_, | 311 Fatal(context_, |
| 311 "Failed to get module " + module_name + " to call " + method_name); | 312 "Failed to get module " + module_name + " to call " + method_name); |
| 312 return handle_scope.Escape( | 313 return handle_scope.Escape( |
| 313 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); | 314 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); |
| 314 } | 315 } |
| 315 | 316 |
| 316 v8::Local<v8::Value> value = | 317 v8::Local<v8::Value> value = v8::Handle<v8::Object>::Cast(module)->Get( |
| 317 v8::Handle<v8::Object>::Cast(module)->Get( | 318 v8::String::NewFromUtf8(GetIsolate(), method_name.c_str())); |
| 318 v8::String::NewFromUtf8(GetIsolate(), method_name.c_str())); | |
| 319 if (value.IsEmpty() || !value->IsFunction()) { | 319 if (value.IsEmpty() || !value->IsFunction()) { |
| 320 Fatal(context_, module_name + "." + method_name + " is not a function"); | 320 Fatal(context_, module_name + "." + method_name + " is not a function"); |
| 321 return handle_scope.Escape( | 321 return handle_scope.Escape( |
| 322 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); | 322 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); |
| 323 } | 323 } |
| 324 | 324 |
| 325 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); | 325 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); |
| 326 v8::Local<v8::Value> result; | 326 v8::Local<v8::Value> result; |
| 327 { | 327 { |
| 328 v8::TryCatch try_catch; | 328 v8::TryCatch try_catch; |
| 329 try_catch.SetCaptureMessage(true); | 329 try_catch.SetCaptureMessage(true); |
| 330 result = context_->CallFunction(func, argc, argv); | 330 result = context_->CallFunction(func, argc, argv); |
| 331 if (try_catch.HasCaught()) | 331 if (try_catch.HasCaught()) |
| 332 HandleException(try_catch); | 332 HandleException(try_catch); |
| 333 } | 333 } |
| 334 return handle_scope.Escape(result); | 334 return handle_scope.Escape(result); |
| 335 } | 335 } |
| 336 | 336 |
| 337 void ModuleSystem::RegisterNativeHandler(const std::string& name, | 337 void ModuleSystem::RegisterNativeHandler( |
| 338 const std::string& name, | |
| 338 scoped_ptr<NativeHandler> native_handler) { | 339 scoped_ptr<NativeHandler> native_handler) { |
| 339 native_handler_map_[name] = | 340 native_handler_map_[name] = |
| 340 linked_ptr<NativeHandler>(native_handler.release()); | 341 linked_ptr<NativeHandler>(native_handler.release()); |
| 341 } | 342 } |
| 342 | 343 |
| 343 void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) { | 344 void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) { |
| 344 overridden_native_handlers_.insert(name); | 345 overridden_native_handlers_.insert(name); |
| 345 } | 346 } |
| 346 | 347 |
| 347 void ModuleSystem::RunString(const std::string& code, const std::string& name) { | 348 void ModuleSystem::RunString(const std::string& code, const std::string& name) { |
| 348 v8::HandleScope handle_scope(GetIsolate()); | 349 v8::HandleScope handle_scope(GetIsolate()); |
| 349 RunString(v8::String::NewFromUtf8(GetIsolate(), code.c_str()), | 350 RunString(v8::String::NewFromUtf8(GetIsolate(), code.c_str()), |
| 350 v8::String::NewFromUtf8(GetIsolate(), name.c_str())); | 351 v8::String::NewFromUtf8(GetIsolate(), name.c_str())); |
| 351 } | 352 } |
| 352 | 353 |
| 353 // static | 354 // static |
| 354 void ModuleSystem::NativeLazyFieldGetter( | 355 void ModuleSystem::NativeLazyFieldGetter( |
| 355 v8::Local<v8::String> property, | 356 v8::Local<v8::String> property, |
| 356 const v8::PropertyCallbackInfo<v8::Value>& info) { | 357 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 357 LazyFieldGetterInner(property, | 358 LazyFieldGetterInner(property, info, &ModuleSystem::RequireNativeFromString); |
| 358 info, | |
| 359 &ModuleSystem::RequireNativeFromString); | |
| 360 } | 359 } |
| 361 | 360 |
| 362 // static | 361 // static |
| 363 void ModuleSystem::LazyFieldGetter( | 362 void ModuleSystem::LazyFieldGetter( |
| 364 v8::Local<v8::String> property, | 363 v8::Local<v8::String> property, |
| 365 const v8::PropertyCallbackInfo<v8::Value>& info) { | 364 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 366 LazyFieldGetterInner(property, info, &ModuleSystem::Require); | 365 LazyFieldGetterInner(property, info, &ModuleSystem::Require); |
| 367 } | 366 } |
| 368 | 367 |
| 369 // static | 368 // static |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 384 // ModuleSystem has been deleted. | 383 // ModuleSystem has been deleted. |
| 385 // TODO(kalman): See comment in header file. | 384 // TODO(kalman): See comment in header file. |
| 386 Warn(info.GetIsolate(), | 385 Warn(info.GetIsolate(), |
| 387 "Module system has been deleted, does extension view exist?"); | 386 "Module system has been deleted, does extension view exist?"); |
| 388 return; | 387 return; |
| 389 } | 388 } |
| 390 | 389 |
| 391 ModuleSystem* module_system = static_cast<ModuleSystem*>( | 390 ModuleSystem* module_system = static_cast<ModuleSystem*>( |
| 392 v8::Handle<v8::External>::Cast(module_system_value)->Value()); | 391 v8::Handle<v8::External>::Cast(module_system_value)->Value()); |
| 393 | 392 |
| 394 std::string name = *v8::String::Utf8Value(parameters->Get( | 393 std::string name = |
| 395 v8::String::NewFromUtf8(info.GetIsolate(), kModuleName))->ToString()); | 394 *v8::String::Utf8Value( |
| 395 parameters->Get(v8::String::NewFromUtf8(info.GetIsolate(), | |
| 396 kModuleName))->ToString()); | |
| 396 | 397 |
| 397 // Switch to our v8 context because we need functions created while running | 398 // Switch to our v8 context because we need functions created while running |
| 398 // the require()d module to belong to our context, not the current one. | 399 // the require()d module to belong to our context, not the current one. |
| 399 v8::Context::Scope context_scope(context); | 400 v8::Context::Scope context_scope(context); |
| 400 NativesEnabledScope natives_enabled_scope(module_system); | 401 NativesEnabledScope natives_enabled_scope(module_system); |
| 401 | 402 |
| 402 v8::TryCatch try_catch; | 403 v8::TryCatch try_catch; |
| 403 v8::Handle<v8::Value> module_value = (module_system->*require_function)(name); | 404 v8::Handle<v8::Value> module_value = (module_system->*require_function)(name); |
| 404 if (try_catch.HasCaught()) { | 405 if (try_catch.HasCaught()) { |
| 405 module_system->HandleException(try_catch); | 406 module_system->HandleException(try_catch); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 v8::Handle<v8::Object> object = info.This(); | 439 v8::Handle<v8::Object> object = info.This(); |
| 439 object->Delete(property); | 440 object->Delete(property); |
| 440 object->Set(property, new_field); | 441 object->Set(property, new_field); |
| 441 info.GetReturnValue().Set(new_field); | 442 info.GetReturnValue().Set(new_field); |
| 442 } | 443 } |
| 443 | 444 |
| 444 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, | 445 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, |
| 445 const std::string& field, | 446 const std::string& field, |
| 446 const std::string& module_name, | 447 const std::string& module_name, |
| 447 const std::string& module_field) { | 448 const std::string& module_field) { |
| 448 SetLazyField(object, field, module_name, module_field, | 449 SetLazyField( |
| 449 &ModuleSystem::LazyFieldGetter); | 450 object, field, module_name, module_field, &ModuleSystem::LazyFieldGetter); |
| 450 } | 451 } |
| 451 | 452 |
| 452 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, | 453 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, |
| 453 const std::string& field, | 454 const std::string& field, |
| 454 const std::string& module_name, | 455 const std::string& module_name, |
| 455 const std::string& module_field, | 456 const std::string& module_field, |
| 456 v8::AccessorGetterCallback getter) { | 457 v8::AccessorGetterCallback getter) { |
| 457 v8::HandleScope handle_scope(GetIsolate()); | 458 v8::HandleScope handle_scope(GetIsolate()); |
| 458 v8::Handle<v8::Object> parameters = v8::Object::New(GetIsolate()); | 459 v8::Handle<v8::Object> parameters = v8::Object::New(GetIsolate()); |
| 459 parameters->Set(v8::String::NewFromUtf8(GetIsolate(), kModuleName), | 460 parameters->Set(v8::String::NewFromUtf8(GetIsolate(), kModuleName), |
| 460 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); | 461 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); |
| 461 parameters->Set(v8::String::NewFromUtf8(GetIsolate(), kModuleField), | 462 parameters->Set(v8::String::NewFromUtf8(GetIsolate(), kModuleField), |
| 462 v8::String::NewFromUtf8(GetIsolate(), module_field.c_str())); | 463 v8::String::NewFromUtf8(GetIsolate(), module_field.c_str())); |
| 463 object->SetAccessor(v8::String::NewFromUtf8(GetIsolate(), field.c_str()), | 464 object->SetAccessor(v8::String::NewFromUtf8(GetIsolate(), field.c_str()), |
| 464 getter, | 465 getter, |
| 465 NULL, | 466 NULL, |
| 466 parameters); | 467 parameters); |
| 467 } | 468 } |
| 468 | 469 |
| 469 void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, | 470 void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, |
| 470 const std::string& field, | 471 const std::string& field, |
| 471 const std::string& module_name, | 472 const std::string& module_name, |
| 472 const std::string& module_field) { | 473 const std::string& module_field) { |
| 473 SetLazyField(object, field, module_name, module_field, | 474 SetLazyField(object, |
| 474 &ModuleSystem::NativeLazyFieldGetter); | 475 field, |
| 476 module_name, | |
| 477 module_field, | |
| 478 &ModuleSystem::NativeLazyFieldGetter); | |
| 475 } | 479 } |
| 476 | 480 |
| 477 | |
| 478 v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, | 481 v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, |
| 479 v8::Handle<v8::String> name) { | 482 v8::Handle<v8::String> name) { |
| 480 v8::EscapableHandleScope handle_scope(GetIsolate()); | 483 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 481 v8::Context::Scope context_scope(context()->v8_context()); | 484 v8::Context::Scope context_scope(context()->v8_context()); |
| 482 | 485 |
| 483 // Prepend extensions:: to |name| so that internal code can be differentiated | 486 // Prepend extensions:: to |name| so that internal code can be differentiated |
| 484 // from external code in stack traces. This has no effect on behaviour. | 487 // from external code in stack traces. This has no effect on behaviour. |
| 485 std::string internal_name = base::StringPrintf("extensions::%s", | 488 std::string internal_name = |
| 486 *v8::String::Utf8Value(name)); | 489 base::StringPrintf("extensions::%s", *v8::String::Utf8Value(name)); |
| 487 | 490 |
| 488 blink::WebScopedMicrotaskSuppression suppression; | 491 blink::WebScopedMicrotaskSuppression suppression; |
| 489 v8::TryCatch try_catch; | 492 v8::TryCatch try_catch; |
| 490 try_catch.SetCaptureMessage(true); | 493 try_catch.SetCaptureMessage(true); |
| 491 v8::Handle<v8::Script> script( | 494 v8::Handle<v8::Script> script( |
| 492 v8::Script::Compile(code, | 495 v8::Script::Compile(code, |
| 493 v8::String::NewFromUtf8(GetIsolate(), | 496 v8::String::NewFromUtf8(GetIsolate(), |
| 494 internal_name.c_str(), | 497 internal_name.c_str(), |
| 495 v8::String::kNormalString, | 498 v8::String::kNormalString, |
| 496 internal_name.size()))); | 499 internal_name.size()))); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 v8::String::NewFromUtf8(GetIsolate(), "privates"); | 576 v8::String::NewFromUtf8(GetIsolate(), "privates"); |
| 574 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); | 577 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); |
| 575 if (privates.IsEmpty()) { | 578 if (privates.IsEmpty()) { |
| 576 privates = v8::Object::New(args.GetIsolate()); | 579 privates = v8::Object::New(args.GetIsolate()); |
| 577 obj->SetHiddenValue(privates_key, privates); | 580 obj->SetHiddenValue(privates_key, privates); |
| 578 } | 581 } |
| 579 args.GetReturnValue().Set(privates); | 582 args.GetReturnValue().Set(privates); |
| 580 } | 583 } |
| 581 | 584 |
| 582 } // namespace extensions | 585 } // namespace extensions |
| OLD | NEW |