Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/extensions/module_system.h" | 5 #include "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/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 9 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 11 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "chrome/common/chrome_switches.h" | |
| 12 #include "chrome/common/extensions/extension_messages.h" | 14 #include "chrome/common/extensions/extension_messages.h" |
| 13 #include "chrome/renderer/extensions/chrome_v8_context.h" | 15 #include "chrome/renderer/extensions/chrome_v8_context.h" |
| 14 #include "chrome/renderer/extensions/console.h" | 16 #include "chrome/renderer/extensions/console.h" |
| 15 #include "content/public/renderer/render_view.h" | 17 #include "content/public/renderer/render_view.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSup pression.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSup pression.h" |
| 18 | 20 |
| 19 namespace extensions { | 21 namespace extensions { |
| 20 | 22 |
| 21 namespace { | 23 namespace { |
| 22 | 24 |
| 23 const char* kModuleSystem = "module_system"; | 25 const char* kModuleSystem = "module_system"; |
| 24 const char* kModuleName = "module_name"; | 26 const char* kModuleName = "module_name"; |
| 25 const char* kModuleField = "module_field"; | 27 const char* kModuleField = "module_field"; |
| 26 const char* kModulesField = "modules"; | 28 const char* kModulesField = "modules"; |
| 27 | 29 |
| 30 // Prepends |extension_id| if it's non-empty to |message|. | |
| 31 std::string PrependExtensionID(const std::string& message, | |
| 32 const std::string& extension_id) { | |
| 33 if (extension_id.empty()) | |
| 34 return message; | |
| 35 return "(" + extension_id + ") " + message; | |
|
Jeffrey Yasskin
2013/06/14 21:42:59
This sort of expression on std::string is slow and
not at google - send to devlin
2013/06/14 22:00:32
Done.
| |
| 36 } | |
| 37 | |
| 38 void Fatal(const std::string& message, const std::string& extension_id) { | |
|
Jeffrey Yasskin
2013/06/14 21:42:59
nit: I would probably put the extension_id first s
not at google - send to devlin
2013/06/14 22:00:32
done.
| |
| 39 // Only crash extension processes. Ideally we would crash on *any* (i.e. web | |
| 40 // too), but given we hardly have code coverage for JS we should be careful | |
| 41 // and not break the web. | |
| 42 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 43 bool is_extension_process = | |
| 44 command_line->HasSwitch(switches::kExtensionProcess) || | |
| 45 command_line->HasSwitch(switches::kSingleProcess); | |
|
Jeffrey Yasskin
2013/06/14 21:42:59
You need a comment justifying crashing the whole b
not at google - send to devlin
2013/06/14 22:00:32
Done.
| |
| 46 std::string with_extension_id = PrependExtensionID(message, extension_id); | |
| 47 if (is_extension_process) | |
|
Jeffrey Yasskin
2013/06/14 21:42:59
Maybe restrict this to the dev or even canary chan
not at google - send to devlin
2013/06/14 22:00:32
As in - you want it to crash in web pages, or you
Jeffrey Yasskin
2013/06/14 22:11:22
I think I'd want it to never crash at all on stabl
not at google - send to devlin
2013/06/14 22:27:44
True on the case of crashing in new situations; I
| |
| 48 console::Fatal(v8::Context::GetCalling(), with_extension_id); | |
| 49 else | |
| 50 console::Error(v8::Context::GetCalling(), with_extension_id); | |
| 51 } | |
| 52 | |
| 53 void Warn(const std::string& message, const std::string& extension_id) { | |
| 54 console::Warn(v8::Context::GetCalling(), | |
| 55 PrependExtensionID(message, extension_id)); | |
| 56 } | |
| 57 | |
| 28 // Default exception handler which logs the exception. | 58 // Default exception handler which logs the exception. |
| 29 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { | 59 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { |
| 30 public: | 60 public: |
| 61 explicit DefaultExceptionHandler(const std::string& extension_id) | |
| 62 : extension_id_(extension_id) {} | |
| 63 | |
| 31 // Fatally dumps the debug info from |try_catch| to the console. | 64 // Fatally dumps the debug info from |try_catch| to the console. |
| 32 // Make sure this is never used for exceptions that originate in external | 65 // Make sure this is never used for exceptions that originate in external |
| 33 // code! | 66 // code! |
| 34 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { | 67 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { |
| 35 v8::HandleScope handle_scope; | 68 v8::HandleScope handle_scope; |
| 36 std::string stack_trace = "<stack trace unavailable>"; | 69 std::string stack_trace = "<stack trace unavailable>"; |
| 37 if (!try_catch.StackTrace().IsEmpty()) { | 70 if (!try_catch.StackTrace().IsEmpty()) { |
| 38 v8::String::Utf8Value stack_value(try_catch.StackTrace()); | 71 v8::String::Utf8Value stack_value(try_catch.StackTrace()); |
| 39 if (*stack_value) | 72 if (*stack_value) |
| 40 stack_trace.assign(*stack_value, stack_value.length()); | 73 stack_trace.assign(*stack_value, stack_value.length()); |
| 41 else | 74 else |
| 42 stack_trace = "<could not convert stack trace to string>"; | 75 stack_trace = "<could not convert stack trace to string>"; |
| 43 } | 76 } |
| 44 console::Fatal(v8::Context::GetCalling(), | 77 Fatal(CreateExceptionString(try_catch) + "{" + stack_trace + "}", |
| 45 CreateExceptionString(try_catch) + "{" + stack_trace + "}"); | 78 extension_id_); |
| 46 } | 79 } |
| 80 | |
| 81 private: | |
| 82 std::string extension_id_; | |
| 47 }; | 83 }; |
| 48 | 84 |
| 49 } // namespace | 85 } // namespace |
| 50 | 86 |
| 51 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( | 87 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( |
| 52 const v8::TryCatch& try_catch) { | 88 const v8::TryCatch& try_catch) { |
| 53 v8::Handle<v8::Message> message(try_catch.Message()); | 89 v8::Handle<v8::Message> message(try_catch.Message()); |
| 54 if (message.IsEmpty()) { | 90 if (message.IsEmpty()) { |
| 55 return "try_catch has no message"; | 91 return "try_catch has no message"; |
| 56 } | 92 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 73 message->GetLineNumber(), | 109 message->GetLineNumber(), |
| 74 error_message.c_str()); | 110 error_message.c_str()); |
| 75 } | 111 } |
| 76 | 112 |
| 77 ModuleSystem::ModuleSystem(ChromeV8Context* context, | 113 ModuleSystem::ModuleSystem(ChromeV8Context* context, |
| 78 SourceMap* source_map) | 114 SourceMap* source_map) |
| 79 : ObjectBackedNativeHandler(context), | 115 : ObjectBackedNativeHandler(context), |
| 80 context_(context), | 116 context_(context), |
| 81 source_map_(source_map), | 117 source_map_(source_map), |
| 82 natives_enabled_(0), | 118 natives_enabled_(0), |
| 83 exception_handler_(new DefaultExceptionHandler()) { | 119 exception_handler_( |
| 120 new DefaultExceptionHandler(context->GetExtensionID())) { | |
| 84 RouteFunction("require", | 121 RouteFunction("require", |
| 85 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 122 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
| 86 RouteFunction("requireNative", | 123 RouteFunction("requireNative", |
| 87 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); | 124 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); |
| 88 | 125 |
| 89 v8::Handle<v8::Object> global(context->v8_context()->Global()); | 126 v8::Handle<v8::Object> global(context->v8_context()->Global()); |
| 90 global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); | 127 global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); |
| 91 global->SetHiddenValue(v8::String::New(kModuleSystem), | 128 global->SetHiddenValue(v8::String::New(kModuleSystem), |
| 92 v8::External::New(this)); | 129 v8::External::New(this)); |
| 93 } | 130 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 v8::Context::Scope context_scope(context()->v8_context()); | 188 v8::Context::Scope context_scope(context()->v8_context()); |
| 152 | 189 |
| 153 v8::Handle<v8::Object> global(context()->v8_context()->Global()); | 190 v8::Handle<v8::Object> global(context()->v8_context()->Global()); |
| 154 | 191 |
| 155 // The module system might have been deleted. This can happen if a different | 192 // The module system might have been deleted. This can happen if a different |
| 156 // context keeps a reference to us, but our frame is destroyed (e.g. | 193 // context keeps a reference to us, but our frame is destroyed (e.g. |
| 157 // background page keeps reference to chrome object in a closed popup). | 194 // background page keeps reference to chrome object in a closed popup). |
| 158 v8::Handle<v8::Value> modules_value = | 195 v8::Handle<v8::Value> modules_value = |
| 159 global->GetHiddenValue(v8::String::New(kModulesField)); | 196 global->GetHiddenValue(v8::String::New(kModulesField)); |
| 160 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { | 197 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { |
| 161 console::Warn(v8::Context::GetCalling(), "Extension view no longer exists"); | 198 Warn("Extension view no longer exists", context_->GetExtensionID()); |
| 162 return v8::Undefined(); | 199 return v8::Undefined(); |
| 163 } | 200 } |
| 164 | 201 |
| 165 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value)); | 202 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value)); |
| 166 v8::Handle<v8::Value> exports(modules->Get(module_name)); | 203 v8::Handle<v8::Value> exports(modules->Get(module_name)); |
| 167 if (!exports->IsUndefined()) | 204 if (!exports->IsUndefined()) |
| 168 return handle_scope.Close(exports); | 205 return handle_scope.Close(exports); |
| 169 | 206 |
| 170 std::string module_name_str = *v8::String::AsciiValue(module_name); | 207 std::string module_name_str = *v8::String::AsciiValue(module_name); |
| 171 v8::Handle<v8::Value> source(GetSource(module_name_str)); | 208 v8::Handle<v8::Value> source(GetSource(module_name_str)); |
| 172 if (source.IsEmpty() || source->IsUndefined()) { | 209 if (source.IsEmpty() || source->IsUndefined()) { |
| 173 console::Error(v8::Context::GetCalling(), | 210 Fatal("No source for require(" + module_name_str + ")", |
| 174 "No source for require(" + module_name_str + ")"); | 211 context_->GetExtensionID()); |
| 175 return v8::Undefined(); | 212 return v8::Undefined(); |
| 176 } | 213 } |
| 177 v8::Handle<v8::String> wrapped_source(WrapSource( | 214 v8::Handle<v8::String> wrapped_source(WrapSource( |
| 178 v8::Handle<v8::String>::Cast(source))); | 215 v8::Handle<v8::String>::Cast(source))); |
| 179 // Modules are wrapped in (function(){...}) so they always return functions. | 216 // Modules are wrapped in (function(){...}) so they always return functions. |
| 180 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); | 217 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); |
| 181 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 218 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { |
| 182 console::Error(v8::Context::GetCalling(), | 219 Fatal("Bad source for require(" + module_name_str + ")", |
| 183 "Bad source for require(" + module_name_str + ")"); | 220 context_->GetExtensionID()); |
| 184 return v8::Undefined(); | 221 return v8::Undefined(); |
| 185 } | 222 } |
| 186 | 223 |
| 187 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 224 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); |
| 188 | 225 |
| 189 exports = v8::Object::New(); | 226 exports = v8::Object::New(); |
| 190 v8::Handle<v8::Object> natives(NewInstance()); | 227 v8::Handle<v8::Object> natives(NewInstance()); |
| 191 v8::Handle<v8::Value> args[] = { | 228 v8::Handle<v8::Value> args[] = { |
| 192 natives->Get(v8::String::NewSymbol("require")), | 229 natives->Get(v8::String::NewSymbol("require")), |
| 193 natives->Get(v8::String::NewSymbol("requireNative")), | 230 natives->Get(v8::String::NewSymbol("requireNative")), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 235 v8::Context::Scope context_scope(context()->v8_context()); | 272 v8::Context::Scope context_scope(context()->v8_context()); |
| 236 | 273 |
| 237 v8::Local<v8::Value> module; | 274 v8::Local<v8::Value> module; |
| 238 { | 275 { |
| 239 NativesEnabledScope natives_enabled(this); | 276 NativesEnabledScope natives_enabled(this); |
| 240 module = v8::Local<v8::Value>::New( | 277 module = v8::Local<v8::Value>::New( |
| 241 RequireForJsInner(v8::String::New(module_name.c_str()))); | 278 RequireForJsInner(v8::String::New(module_name.c_str()))); |
| 242 } | 279 } |
| 243 | 280 |
| 244 if (module.IsEmpty() || !module->IsObject()) { | 281 if (module.IsEmpty() || !module->IsObject()) { |
| 245 console::Error( | 282 Fatal("Failed to get module " + module_name + " to call " + method_name, |
| 246 v8::Context::GetCalling(), | 283 context_->GetExtensionID()); |
| 247 "Failed to get module " + module_name + " to call " + method_name); | |
| 248 return handle_scope.Close(v8::Undefined()); | 284 return handle_scope.Close(v8::Undefined()); |
| 249 } | 285 } |
| 250 | 286 |
| 251 v8::Local<v8::Value> value = | 287 v8::Local<v8::Value> value = |
| 252 v8::Handle<v8::Object>::Cast(module)->Get( | 288 v8::Handle<v8::Object>::Cast(module)->Get( |
| 253 v8::String::New(method_name.c_str())); | 289 v8::String::New(method_name.c_str())); |
| 254 if (value.IsEmpty() || !value->IsFunction()) { | 290 if (value.IsEmpty() || !value->IsFunction()) { |
| 255 console::Error(v8::Context::GetCalling(), | 291 Fatal(module_name + "." + method_name + " is not a function", |
| 256 module_name + "." + method_name + " is not a function"); | 292 context_->GetExtensionID()); |
| 257 return handle_scope.Close(v8::Undefined()); | 293 return handle_scope.Close(v8::Undefined()); |
| 258 } | 294 } |
| 259 | 295 |
| 260 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); | 296 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); |
| 261 v8::Local<v8::Value> result; | 297 v8::Local<v8::Value> result; |
| 262 { | 298 { |
| 263 v8::TryCatch try_catch; | 299 v8::TryCatch try_catch; |
| 264 try_catch.SetCaptureMessage(true); | 300 try_catch.SetCaptureMessage(true); |
| 265 result = context_->CallFunction(func, argc, argv); | 301 result = context_->CallFunction(func, argc, argv); |
| 266 if (try_catch.HasCaught()) | 302 if (try_catch.HasCaught()) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 v8::HandleScope handle_scope; | 346 v8::HandleScope handle_scope; |
| 311 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); | 347 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); |
| 312 // This context should be the same as context()->v8_context(). | 348 // This context should be the same as context()->v8_context(). |
| 313 v8::Handle<v8::Context> context = parameters->CreationContext(); | 349 v8::Handle<v8::Context> context = parameters->CreationContext(); |
| 314 v8::Handle<v8::Object> global(context->Global()); | 350 v8::Handle<v8::Object> global(context->Global()); |
| 315 v8::Handle<v8::Value> module_system_value = | 351 v8::Handle<v8::Value> module_system_value = |
| 316 global->GetHiddenValue(v8::String::New(kModuleSystem)); | 352 global->GetHiddenValue(v8::String::New(kModuleSystem)); |
| 317 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { | 353 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { |
| 318 // ModuleSystem has been deleted. | 354 // ModuleSystem has been deleted. |
| 319 // TODO(kalman): See comment in header file. | 355 // TODO(kalman): See comment in header file. |
| 320 console::Warn(v8::Context::GetCalling(), | 356 Warn("Module system has been deleted, does extension view exist?", ""); |
| 321 "Module system has been deleted, does extension view exist?"); | |
| 322 return; | 357 return; |
| 323 } | 358 } |
| 324 | 359 |
| 325 ModuleSystem* module_system = static_cast<ModuleSystem*>( | 360 ModuleSystem* module_system = static_cast<ModuleSystem*>( |
| 326 v8::Handle<v8::External>::Cast(module_system_value)->Value()); | 361 v8::Handle<v8::External>::Cast(module_system_value)->Value()); |
| 327 | 362 |
| 328 std::string name = *v8::String::AsciiValue( | 363 std::string name = *v8::String::AsciiValue( |
| 329 parameters->Get(v8::String::New(kModuleName))->ToString()); | 364 parameters->Get(v8::String::New(kModuleName))->ToString()); |
| 330 | 365 |
| 331 // Switch to our v8 context because we need functions created while running | 366 // Switch to our v8 context because we need functions created while running |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 343 // require_function will have already logged this, we don't need to. | 378 // require_function will have already logged this, we don't need to. |
| 344 return; | 379 return; |
| 345 } | 380 } |
| 346 | 381 |
| 347 v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast(module_value); | 382 v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast(module_value); |
| 348 v8::Handle<v8::String> field = | 383 v8::Handle<v8::String> field = |
| 349 parameters->Get(v8::String::New(kModuleField))->ToString(); | 384 parameters->Get(v8::String::New(kModuleField))->ToString(); |
| 350 | 385 |
| 351 if (!module->Has(field)) { | 386 if (!module->Has(field)) { |
| 352 std::string field_str = *v8::String::AsciiValue(field); | 387 std::string field_str = *v8::String::AsciiValue(field); |
| 353 console::Fatal(v8::Context::GetCalling(), | 388 Fatal("Lazy require of " + name + "." + field_str + " did not " + |
| 354 "Lazy require of " + name + "." + field_str + " did not " + | 389 "set the " + field_str + " field", |
| 355 "set the " + field_str + " field"); | 390 module_system->context_->GetExtensionID()); |
| 356 return; | 391 return; |
| 357 } | 392 } |
| 358 | 393 |
| 359 v8::Local<v8::Value> new_field = module->Get(field); | 394 v8::Local<v8::Value> new_field = module->Get(field); |
| 360 if (try_catch.HasCaught()) { | 395 if (try_catch.HasCaught()) { |
| 361 module_system->HandleException(try_catch); | 396 module_system->HandleException(try_catch); |
| 362 return; | 397 return; |
| 363 } | 398 } |
| 364 | 399 |
| 365 // Ok for it to be undefined, among other things it's how bindings signify | 400 // Ok for it to be undefined, among other things it's how bindings signify |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 } | 480 } |
| 446 | 481 |
| 447 v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( | 482 v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( |
| 448 const std::string& native_name) { | 483 const std::string& native_name) { |
| 449 if (natives_enabled_ == 0) { | 484 if (natives_enabled_ == 0) { |
| 450 // HACK: if in test throw exception so that we can test the natives-disabled | 485 // HACK: if in test throw exception so that we can test the natives-disabled |
| 451 // logic; however, under normal circumstances, this is programmer error so | 486 // logic; however, under normal circumstances, this is programmer error so |
| 452 // we could crash. | 487 // we could crash. |
| 453 if (exception_handler_) | 488 if (exception_handler_) |
| 454 return v8::ThrowException(v8::String::New("Natives disabled")); | 489 return v8::ThrowException(v8::String::New("Natives disabled")); |
| 455 console::Fatal(v8::Context::GetCalling(), | 490 Fatal("Natives disabled for requireNative(" + native_name + ")", |
| 456 "Natives disabled for requireNative(" + native_name + ")"); | 491 context_->GetExtensionID()); |
| 457 return v8::Undefined(); | 492 return v8::Undefined(); |
| 458 } | 493 } |
| 459 | 494 |
| 460 if (overridden_native_handlers_.count(native_name) > 0u) | 495 if (overridden_native_handlers_.count(native_name) > 0u) |
| 461 return RequireForJsInner(v8::String::New(native_name.c_str())); | 496 return RequireForJsInner(v8::String::New(native_name.c_str())); |
| 462 | 497 |
| 463 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); | 498 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
| 464 if (i == native_handler_map_.end()) { | 499 if (i == native_handler_map_.end()) { |
| 465 console::Fatal( | 500 Fatal("Couldn't find native for requireNative(" + native_name + ")", |
| 466 v8::Context::GetCalling(), | 501 context_->GetExtensionID()); |
| 467 "Couldn't find native for requireNative(" + native_name + ")"); | |
| 468 return v8::Undefined(); | 502 return v8::Undefined(); |
| 469 } | 503 } |
| 470 return i->second->NewInstance(); | 504 return i->second->NewInstance(); |
| 471 } | 505 } |
| 472 | 506 |
| 473 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 507 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { |
| 474 v8::HandleScope handle_scope; | 508 v8::HandleScope handle_scope; |
| 475 v8::Handle<v8::String> left = v8::String::New( | 509 v8::Handle<v8::String> left = v8::String::New( |
| 476 "(function(require, requireNative, exports) {'use strict';"); | 510 "(function(require, requireNative, exports) {'use strict';"); |
| 477 v8::Handle<v8::String> right = v8::String::New("\n})"); | 511 v8::Handle<v8::String> right = v8::String::New("\n})"); |
| 478 return handle_scope.Close( | 512 return handle_scope.Close( |
| 479 v8::String::Concat(left, v8::String::Concat(source, right))); | 513 v8::String::Concat(left, v8::String::Concat(source, right))); |
| 480 } | 514 } |
| 481 | 515 |
| 482 } // namespace extensions | 516 } // namespace extensions |
| OLD | NEW |