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 |