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 "chrome/renderer/extensions/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" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 // Default exception handler which logs the exception. | 67 // Default exception handler which logs the exception. |
68 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { | 68 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { |
69 public: | 69 public: |
70 explicit DefaultExceptionHandler(ChromeV8Context* context) | 70 explicit DefaultExceptionHandler(ChromeV8Context* context) |
71 : context_(context) {} | 71 : context_(context) {} |
72 | 72 |
73 // Fatally dumps the debug info from |try_catch| to the console. | 73 // Fatally dumps the debug info from |try_catch| to the console. |
74 // Make sure this is never used for exceptions that originate in external | 74 // Make sure this is never used for exceptions that originate in external |
75 // code! | 75 // code! |
76 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { | 76 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { |
77 v8::HandleScope handle_scope; | 77 v8::HandleScope handle_scope(context_->isolate()); |
78 std::string stack_trace = "<stack trace unavailable>"; | 78 std::string stack_trace = "<stack trace unavailable>"; |
79 if (!try_catch.StackTrace().IsEmpty()) { | 79 if (!try_catch.StackTrace().IsEmpty()) { |
80 v8::String::Utf8Value stack_value(try_catch.StackTrace()); | 80 v8::String::Utf8Value stack_value(try_catch.StackTrace()); |
81 if (*stack_value) | 81 if (*stack_value) |
82 stack_trace.assign(*stack_value, stack_value.length()); | 82 stack_trace.assign(*stack_value, stack_value.length()); |
83 else | 83 else |
84 stack_trace = "<could not convert stack trace to string>"; | 84 stack_trace = "<could not convert stack trace to string>"; |
85 } | 85 } |
86 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}"); | 86 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}"); |
87 } | 87 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 Invalidate(); | 139 Invalidate(); |
140 } | 140 } |
141 | 141 |
142 void ModuleSystem::Invalidate() { | 142 void ModuleSystem::Invalidate() { |
143 if (!is_valid()) | 143 if (!is_valid()) |
144 return; | 144 return; |
145 | 145 |
146 // Clear the module system properties from the global context. It's polite, | 146 // Clear the module system properties from the global context. It's polite, |
147 // and we use this as a signal in lazy handlers that we no longer exist. | 147 // and we use this as a signal in lazy handlers that we no longer exist. |
148 { | 148 { |
149 v8::HandleScope scope; | 149 v8::HandleScope scope(GetIsolate()); |
150 v8::Handle<v8::Object> global = context()->v8_context()->Global(); | 150 v8::Handle<v8::Object> global = context()->v8_context()->Global(); |
151 global->DeleteHiddenValue(v8::String::New(kModulesField)); | 151 global->DeleteHiddenValue(v8::String::New(kModulesField)); |
152 global->DeleteHiddenValue(v8::String::New(kModuleSystem)); | 152 global->DeleteHiddenValue(v8::String::New(kModuleSystem)); |
153 } | 153 } |
154 | 154 |
155 // Invalidate all of the successfully required handlers we own. | 155 // Invalidate all of the successfully required handlers we own. |
156 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); | 156 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); |
157 it != native_handler_map_.end(); ++it) { | 157 it != native_handler_map_.end(); ++it) { |
158 it->second->Invalidate(); | 158 it->second->Invalidate(); |
159 } | 159 } |
(...skipping 10 matching lines...) Expand all Loading... |
170 ModuleSystem::NativesEnabledScope::~NativesEnabledScope() { | 170 ModuleSystem::NativesEnabledScope::~NativesEnabledScope() { |
171 module_system_->natives_enabled_--; | 171 module_system_->natives_enabled_--; |
172 CHECK_GE(module_system_->natives_enabled_, 0); | 172 CHECK_GE(module_system_->natives_enabled_, 0); |
173 } | 173 } |
174 | 174 |
175 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { | 175 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { |
176 exception_handler_->HandleUncaughtException(try_catch); | 176 exception_handler_->HandleUncaughtException(try_catch); |
177 } | 177 } |
178 | 178 |
179 v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { | 179 v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { |
180 v8::HandleScope handle_scope; | 180 v8::HandleScope handle_scope(GetIsolate()); |
181 return handle_scope.Close( | 181 return handle_scope.Close( |
182 RequireForJsInner(v8::String::New(module_name.c_str()))); | 182 RequireForJsInner(v8::String::New(module_name.c_str()))); |
183 } | 183 } |
184 | 184 |
185 void ModuleSystem::RequireForJs( | 185 void ModuleSystem::RequireForJs( |
186 const v8::FunctionCallbackInfo<v8::Value>& args) { | 186 const v8::FunctionCallbackInfo<v8::Value>& args) { |
187 v8::Handle<v8::String> module_name = args[0]->ToString(); | 187 v8::Handle<v8::String> module_name = args[0]->ToString(); |
188 args.GetReturnValue().Set(RequireForJsInner(module_name)); | 188 args.GetReturnValue().Set(RequireForJsInner(module_name)); |
189 } | 189 } |
190 | 190 |
191 v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( | 191 v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( |
192 v8::Handle<v8::String> module_name) { | 192 v8::Handle<v8::String> module_name) { |
193 v8::HandleScope handle_scope; | 193 v8::HandleScope handle_scope(GetIsolate()); |
194 v8::Context::Scope context_scope(context()->v8_context()); | 194 v8::Context::Scope context_scope(context()->v8_context()); |
195 | 195 |
196 v8::Handle<v8::Object> global(context()->v8_context()->Global()); | 196 v8::Handle<v8::Object> global(context()->v8_context()->Global()); |
197 | 197 |
198 // The module system might have been deleted. This can happen if a different | 198 // The module system might have been deleted. This can happen if a different |
199 // context keeps a reference to us, but our frame is destroyed (e.g. | 199 // context keeps a reference to us, but our frame is destroyed (e.g. |
200 // background page keeps reference to chrome object in a closed popup). | 200 // background page keeps reference to chrome object in a closed popup). |
201 v8::Handle<v8::Value> modules_value = | 201 v8::Handle<v8::Value> modules_value = |
202 global->GetHiddenValue(v8::String::New(kModulesField)); | 202 global->GetHiddenValue(v8::String::New(kModulesField)); |
203 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { | 203 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 return v8::Undefined(); | 256 return v8::Undefined(); |
257 } | 257 } |
258 } | 258 } |
259 modules->Set(module_name, exports); | 259 modules->Set(module_name, exports); |
260 return handle_scope.Close(exports); | 260 return handle_scope.Close(exports); |
261 } | 261 } |
262 | 262 |
263 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( | 263 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
264 const std::string& module_name, | 264 const std::string& module_name, |
265 const std::string& method_name) { | 265 const std::string& method_name) { |
266 v8::HandleScope handle_scope; | 266 v8::HandleScope handle_scope(GetIsolate()); |
267 v8::Handle<v8::Value> no_args; | 267 v8::Handle<v8::Value> no_args; |
268 return CallModuleMethod(module_name, method_name, 0, &no_args); | 268 return CallModuleMethod(module_name, method_name, 0, &no_args); |
269 } | 269 } |
270 | 270 |
271 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( | 271 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
272 const std::string& module_name, | 272 const std::string& module_name, |
273 const std::string& method_name, | 273 const std::string& method_name, |
274 std::vector<v8::Handle<v8::Value> >* args) { | 274 std::vector<v8::Handle<v8::Value> >* args) { |
275 return CallModuleMethod( | 275 return CallModuleMethod( |
276 module_name, method_name, args->size(), vector_as_array(args)); | 276 module_name, method_name, args->size(), vector_as_array(args)); |
277 } | 277 } |
278 | 278 |
279 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( | 279 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
280 const std::string& module_name, | 280 const std::string& module_name, |
281 const std::string& method_name, | 281 const std::string& method_name, |
282 int argc, | 282 int argc, |
283 v8::Handle<v8::Value> argv[]) { | 283 v8::Handle<v8::Value> argv[]) { |
284 TRACE_EVENT2("v8", "v8.callModuleMethod", | 284 TRACE_EVENT2("v8", "v8.callModuleMethod", |
285 "module_name", module_name, | 285 "module_name", module_name, |
286 "method_name", method_name); | 286 "method_name", method_name); |
287 | 287 |
288 v8::HandleScope handle_scope; | 288 v8::HandleScope handle_scope(GetIsolate()); |
289 v8::Context::Scope context_scope(context()->v8_context()); | 289 v8::Context::Scope context_scope(context()->v8_context()); |
290 | 290 |
291 v8::Local<v8::Value> module; | 291 v8::Local<v8::Value> module; |
292 { | 292 { |
293 NativesEnabledScope natives_enabled(this); | 293 NativesEnabledScope natives_enabled(this); |
294 module = v8::Local<v8::Value>::New( | 294 module = v8::Local<v8::Value>::New( |
295 RequireForJsInner(v8::String::New(module_name.c_str()))); | 295 RequireForJsInner(v8::String::New(module_name.c_str()))); |
296 } | 296 } |
297 | 297 |
298 if (module.IsEmpty() || !module->IsObject()) { | 298 if (module.IsEmpty() || !module->IsObject()) { |
(...skipping 26 matching lines...) Expand all Loading... |
325 scoped_ptr<NativeHandler> native_handler) { | 325 scoped_ptr<NativeHandler> native_handler) { |
326 native_handler_map_[name] = | 326 native_handler_map_[name] = |
327 linked_ptr<NativeHandler>(native_handler.release()); | 327 linked_ptr<NativeHandler>(native_handler.release()); |
328 } | 328 } |
329 | 329 |
330 void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) { | 330 void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) { |
331 overridden_native_handlers_.insert(name); | 331 overridden_native_handlers_.insert(name); |
332 } | 332 } |
333 | 333 |
334 void ModuleSystem::RunString(const std::string& code, const std::string& name) { | 334 void ModuleSystem::RunString(const std::string& code, const std::string& name) { |
335 v8::HandleScope handle_scope; | 335 v8::HandleScope handle_scope(GetIsolate()); |
336 RunString(v8::String::New(code.c_str()), v8::String::New(name.c_str())); | 336 RunString(v8::String::New(code.c_str()), v8::String::New(name.c_str())); |
337 } | 337 } |
338 | 338 |
339 // static | 339 // static |
340 void ModuleSystem::NativeLazyFieldGetter( | 340 void ModuleSystem::NativeLazyFieldGetter( |
341 v8::Local<v8::String> property, | 341 v8::Local<v8::String> property, |
342 const v8::PropertyCallbackInfo<v8::Value>& info) { | 342 const v8::PropertyCallbackInfo<v8::Value>& info) { |
343 LazyFieldGetterInner(property, | 343 LazyFieldGetterInner(property, |
344 info, | 344 info, |
345 &ModuleSystem::RequireNativeFromString); | 345 &ModuleSystem::RequireNativeFromString); |
346 } | 346 } |
347 | 347 |
348 // static | 348 // static |
349 void ModuleSystem::LazyFieldGetter( | 349 void ModuleSystem::LazyFieldGetter( |
350 v8::Local<v8::String> property, | 350 v8::Local<v8::String> property, |
351 const v8::PropertyCallbackInfo<v8::Value>& info) { | 351 const v8::PropertyCallbackInfo<v8::Value>& info) { |
352 LazyFieldGetterInner(property, info, &ModuleSystem::Require); | 352 LazyFieldGetterInner(property, info, &ModuleSystem::Require); |
353 } | 353 } |
354 | 354 |
355 // static | 355 // static |
356 void ModuleSystem::LazyFieldGetterInner( | 356 void ModuleSystem::LazyFieldGetterInner( |
357 v8::Local<v8::String> property, | 357 v8::Local<v8::String> property, |
358 const v8::PropertyCallbackInfo<v8::Value>& info, | 358 const v8::PropertyCallbackInfo<v8::Value>& info, |
359 RequireFunction require_function) { | 359 RequireFunction require_function) { |
360 CHECK(!info.Data().IsEmpty()); | 360 CHECK(!info.Data().IsEmpty()); |
361 CHECK(info.Data()->IsObject()); | 361 CHECK(info.Data()->IsObject()); |
362 v8::HandleScope handle_scope; | 362 v8::HandleScope handle_scope(info.GetIsolate()); |
363 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); | 363 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); |
364 // This context should be the same as context()->v8_context(). | 364 // This context should be the same as context()->v8_context(). |
365 v8::Handle<v8::Context> context = parameters->CreationContext(); | 365 v8::Handle<v8::Context> context = parameters->CreationContext(); |
366 v8::Handle<v8::Object> global(context->Global()); | 366 v8::Handle<v8::Object> global(context->Global()); |
367 v8::Handle<v8::Value> module_system_value = | 367 v8::Handle<v8::Value> module_system_value = |
368 global->GetHiddenValue(v8::String::New(kModuleSystem)); | 368 global->GetHiddenValue(v8::String::New(kModuleSystem)); |
369 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { | 369 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { |
370 // ModuleSystem has been deleted. | 370 // ModuleSystem has been deleted. |
371 // TODO(kalman): See comment in header file. | 371 // TODO(kalman): See comment in header file. |
372 Warn("Module system has been deleted, does extension view exist?"); | 372 Warn("Module system has been deleted, does extension view exist?"); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 const std::string& module_field) { | 431 const std::string& module_field) { |
432 SetLazyField(object, field, module_name, module_field, | 432 SetLazyField(object, field, module_name, module_field, |
433 &ModuleSystem::LazyFieldGetter); | 433 &ModuleSystem::LazyFieldGetter); |
434 } | 434 } |
435 | 435 |
436 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, | 436 void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, |
437 const std::string& field, | 437 const std::string& field, |
438 const std::string& module_name, | 438 const std::string& module_name, |
439 const std::string& module_field, | 439 const std::string& module_field, |
440 v8::AccessorGetterCallback getter) { | 440 v8::AccessorGetterCallback getter) { |
441 v8::HandleScope handle_scope; | 441 v8::HandleScope handle_scope(GetIsolate()); |
442 v8::Handle<v8::Object> parameters = v8::Object::New(); | 442 v8::Handle<v8::Object> parameters = v8::Object::New(); |
443 parameters->Set(v8::String::New(kModuleName), | 443 parameters->Set(v8::String::New(kModuleName), |
444 v8::String::New(module_name.c_str())); | 444 v8::String::New(module_name.c_str())); |
445 parameters->Set(v8::String::New(kModuleField), | 445 parameters->Set(v8::String::New(kModuleField), |
446 v8::String::New(module_field.c_str())); | 446 v8::String::New(module_field.c_str())); |
447 object->SetAccessor(v8::String::New(field.c_str()), | 447 object->SetAccessor(v8::String::New(field.c_str()), |
448 getter, | 448 getter, |
449 NULL, | 449 NULL, |
450 parameters); | 450 parameters); |
451 } | 451 } |
452 | 452 |
453 void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, | 453 void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, |
454 const std::string& field, | 454 const std::string& field, |
455 const std::string& module_name, | 455 const std::string& module_name, |
456 const std::string& module_field) { | 456 const std::string& module_field) { |
457 SetLazyField(object, field, module_name, module_field, | 457 SetLazyField(object, field, module_name, module_field, |
458 &ModuleSystem::NativeLazyFieldGetter); | 458 &ModuleSystem::NativeLazyFieldGetter); |
459 } | 459 } |
460 | 460 |
| 461 |
| 462 v8::Isolate* ModuleSystem::GetIsolate() const { |
| 463 return context_->isolate(); |
| 464 } |
| 465 |
461 v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, | 466 v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, |
462 v8::Handle<v8::String> name) { | 467 v8::Handle<v8::String> name) { |
463 v8::HandleScope handle_scope; | 468 v8::HandleScope handle_scope(GetIsolate()); |
464 v8::Context::Scope context_scope(context()->v8_context()); | 469 v8::Context::Scope context_scope(context()->v8_context()); |
465 | 470 |
466 WebKit::WebScopedMicrotaskSuppression suppression; | 471 WebKit::WebScopedMicrotaskSuppression suppression; |
467 v8::TryCatch try_catch; | 472 v8::TryCatch try_catch; |
468 try_catch.SetCaptureMessage(true); | 473 try_catch.SetCaptureMessage(true); |
469 v8::Handle<v8::Script> script(v8::Script::New(code, name)); | 474 v8::Handle<v8::Script> script(v8::Script::New(code, name)); |
470 if (try_catch.HasCaught()) { | 475 if (try_catch.HasCaught()) { |
471 HandleException(try_catch); | 476 HandleException(try_catch); |
472 return v8::Undefined(); | 477 return v8::Undefined(); |
473 } | 478 } |
474 | 479 |
475 v8::Handle<v8::Value> result = script->Run(); | 480 v8::Handle<v8::Value> result = script->Run(); |
476 if (try_catch.HasCaught()) { | 481 if (try_catch.HasCaught()) { |
477 HandleException(try_catch); | 482 HandleException(try_catch); |
478 return v8::Undefined(); | 483 return v8::Undefined(); |
479 } | 484 } |
480 | 485 |
481 return handle_scope.Close(result); | 486 return handle_scope.Close(result); |
482 } | 487 } |
483 | 488 |
484 v8::Handle<v8::Value> ModuleSystem::GetSource(const std::string& module_name) { | 489 v8::Handle<v8::Value> ModuleSystem::GetSource(const std::string& module_name) { |
485 v8::HandleScope handle_scope; | 490 v8::HandleScope handle_scope(GetIsolate()); |
486 if (!source_map_->Contains(module_name)) | 491 if (!source_map_->Contains(module_name)) |
487 return v8::Undefined(); | 492 return v8::Undefined(); |
488 return handle_scope.Close(source_map_->GetSource(module_name)); | 493 return handle_scope.Close(source_map_->GetSource(module_name)); |
489 } | 494 } |
490 | 495 |
491 void ModuleSystem::RequireNative( | 496 void ModuleSystem::RequireNative( |
492 const v8::FunctionCallbackInfo<v8::Value>& args) { | 497 const v8::FunctionCallbackInfo<v8::Value>& args) { |
493 CHECK_EQ(1, args.Length()); | 498 CHECK_EQ(1, args.Length()); |
494 std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); | 499 std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); |
495 args.GetReturnValue().Set(RequireNativeFromString(native_name)); | 500 args.GetReturnValue().Set(RequireNativeFromString(native_name)); |
(...skipping 17 matching lines...) Expand all Loading... |
513 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); | 518 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
514 if (i == native_handler_map_.end()) { | 519 if (i == native_handler_map_.end()) { |
515 Fatal(context_, | 520 Fatal(context_, |
516 "Couldn't find native for requireNative(" + native_name + ")"); | 521 "Couldn't find native for requireNative(" + native_name + ")"); |
517 return v8::Undefined(); | 522 return v8::Undefined(); |
518 } | 523 } |
519 return i->second->NewInstance(); | 524 return i->second->NewInstance(); |
520 } | 525 } |
521 | 526 |
522 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 527 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { |
523 v8::HandleScope handle_scope; | 528 v8::HandleScope handle_scope(GetIsolate()); |
524 // Keep in order with the arguments in RequireForJsInner. | 529 // Keep in order with the arguments in RequireForJsInner. |
525 v8::Handle<v8::String> left = v8::String::New( | 530 v8::Handle<v8::String> left = v8::String::New( |
526 "(function(require, requireNative, exports, " | 531 "(function(require, requireNative, exports, " |
527 "console, " | 532 "console, " |
528 "$Array, $Function, $JSON, $Object, $RegExp, $String) {" | 533 "$Array, $Function, $JSON, $Object, $RegExp, $String) {" |
529 "'use strict';"); | 534 "'use strict';"); |
530 v8::Handle<v8::String> right = v8::String::New("\n})"); | 535 v8::Handle<v8::String> right = v8::String::New("\n})"); |
531 return handle_scope.Close( | 536 return handle_scope.Close( |
532 v8::String::Concat(left, v8::String::Concat(source, right))); | 537 v8::String::Concat(left, v8::String::Concat(source, right))); |
533 } | 538 } |
534 | 539 |
535 } // namespace extensions | 540 } // namespace extensions |
OLD | NEW |