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