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 |