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& extension_id, | |
| 32 const std::string& message) { | |
| 33 std::string with_extension_id = message; | |
| 34 if (!extension_id.empty()) { | |
| 35 with_extension_id += "("; | |
|
Jeffrey Yasskin
2013/06/14 22:11:22
Heh, this will put the extension_id after the mess
not at google - send to devlin
2013/06/14 22:27:44
damnnnnnnn
| |
| 36 with_extension_id += extension_id; | |
| 37 with_extension_id += ") "; | |
| 38 } | |
| 39 return with_extension_id; | |
| 40 } | |
| 41 | |
| 42 void Fatal(const std::string& extension_id, const std::string& message) { | |
| 43 // Only crash extension processes. Ideally we would crash on *any* (i.e. web | |
| 44 // too), but given we hardly have code coverage for JS we should be careful | |
| 45 // and not break the web. | |
| 46 // | |
| 47 // NOTE: make single-process count as an extension process since it's for | |
| 48 // debugging, and we'll almost certainly want to use it to repro them. | |
|
Jeffrey Yasskin
2013/06/14 22:11:22
"them" lacks an antecedent.
not at google - send to devlin
2013/06/14 22:27:44
rephrased.
| |
| 49 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 50 bool is_extension_process = | |
| 51 command_line->HasSwitch(switches::kExtensionProcess) || | |
| 52 command_line->HasSwitch(switches::kSingleProcess); | |
| 53 std::string with_extension_id = PrependExtensionID(extension_id, message); | |
| 54 if (is_extension_process) | |
| 55 console::Fatal(v8::Context::GetCalling(), with_extension_id); | |
| 56 else | |
| 57 console::Error(v8::Context::GetCalling(), with_extension_id); | |
| 58 } | |
| 59 | |
| 60 void Warn(const std::string& extension_id, const std::string& message) { | |
| 61 console::Warn(v8::Context::GetCalling(), | |
| 62 PrependExtensionID(extension_id, message)); | |
| 63 } | |
| 64 | |
| 28 // Default exception handler which logs the exception. | 65 // Default exception handler which logs the exception. |
| 29 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { | 66 class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler { |
| 30 public: | 67 public: |
| 68 explicit DefaultExceptionHandler(const std::string& extension_id) | |
| 69 : extension_id_(extension_id) {} | |
| 70 | |
| 31 // Fatally dumps the debug info from |try_catch| to the console. | 71 // Fatally dumps the debug info from |try_catch| to the console. |
| 32 // 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 |
| 33 // code! | 73 // code! |
| 34 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { | 74 virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE { |
| 35 v8::HandleScope handle_scope; | 75 v8::HandleScope handle_scope; |
| 36 std::string stack_trace = "<stack trace unavailable>"; | 76 std::string stack_trace = "<stack trace unavailable>"; |
| 37 if (!try_catch.StackTrace().IsEmpty()) { | 77 if (!try_catch.StackTrace().IsEmpty()) { |
| 38 v8::String::Utf8Value stack_value(try_catch.StackTrace()); | 78 v8::String::Utf8Value stack_value(try_catch.StackTrace()); |
| 39 if (*stack_value) | 79 if (*stack_value) |
| 40 stack_trace.assign(*stack_value, stack_value.length()); | 80 stack_trace.assign(*stack_value, stack_value.length()); |
| 41 else | 81 else |
| 42 stack_trace = "<could not convert stack trace to string>"; | 82 stack_trace = "<could not convert stack trace to string>"; |
| 43 } | 83 } |
| 44 console::Fatal(v8::Context::GetCalling(), | 84 Fatal(extension_id_, |
| 45 CreateExceptionString(try_catch) + "{" + stack_trace + "}"); | 85 CreateExceptionString(try_catch) + "{" + stack_trace + "}"); |
| 46 } | 86 } |
| 87 | |
| 88 private: | |
| 89 std::string extension_id_; | |
| 47 }; | 90 }; |
| 48 | 91 |
| 49 } // namespace | 92 } // namespace |
| 50 | 93 |
| 51 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( | 94 std::string ModuleSystem::ExceptionHandler::CreateExceptionString( |
| 52 const v8::TryCatch& try_catch) { | 95 const v8::TryCatch& try_catch) { |
| 53 v8::Handle<v8::Message> message(try_catch.Message()); | 96 v8::Handle<v8::Message> message(try_catch.Message()); |
| 54 if (message.IsEmpty()) { | 97 if (message.IsEmpty()) { |
| 55 return "try_catch has no message"; | 98 return "try_catch has no message"; |
| 56 } | 99 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 73 message->GetLineNumber(), | 116 message->GetLineNumber(), |
| 74 error_message.c_str()); | 117 error_message.c_str()); |
| 75 } | 118 } |
| 76 | 119 |
| 77 ModuleSystem::ModuleSystem(ChromeV8Context* context, | 120 ModuleSystem::ModuleSystem(ChromeV8Context* context, |
| 78 SourceMap* source_map) | 121 SourceMap* source_map) |
| 79 : ObjectBackedNativeHandler(context), | 122 : ObjectBackedNativeHandler(context), |
| 80 context_(context), | 123 context_(context), |
| 81 source_map_(source_map), | 124 source_map_(source_map), |
| 82 natives_enabled_(0), | 125 natives_enabled_(0), |
| 83 exception_handler_(new DefaultExceptionHandler()) { | 126 exception_handler_( |
| 127 new DefaultExceptionHandler(context->GetExtensionID())) { | |
| 84 RouteFunction("require", | 128 RouteFunction("require", |
| 85 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 129 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
| 86 RouteFunction("requireNative", | 130 RouteFunction("requireNative", |
| 87 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); | 131 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); |
| 88 | 132 |
| 89 v8::Handle<v8::Object> global(context->v8_context()->Global()); | 133 v8::Handle<v8::Object> global(context->v8_context()->Global()); |
| 90 global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); | 134 global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); |
| 91 global->SetHiddenValue(v8::String::New(kModuleSystem), | 135 global->SetHiddenValue(v8::String::New(kModuleSystem), |
| 92 v8::External::New(this)); | 136 v8::External::New(this)); |
| 93 } | 137 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 v8::Context::Scope context_scope(context()->v8_context()); | 195 v8::Context::Scope context_scope(context()->v8_context()); |
| 152 | 196 |
| 153 v8::Handle<v8::Object> global(context()->v8_context()->Global()); | 197 v8::Handle<v8::Object> global(context()->v8_context()->Global()); |
| 154 | 198 |
| 155 // The module system might have been deleted. This can happen if a different | 199 // 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. | 200 // 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). | 201 // background page keeps reference to chrome object in a closed popup). |
| 158 v8::Handle<v8::Value> modules_value = | 202 v8::Handle<v8::Value> modules_value = |
| 159 global->GetHiddenValue(v8::String::New(kModulesField)); | 203 global->GetHiddenValue(v8::String::New(kModulesField)); |
| 160 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { | 204 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { |
| 161 console::Warn(v8::Context::GetCalling(), "Extension view no longer exists"); | 205 Warn(context_->GetExtensionID(), "Extension view no longer exists"); |
| 162 return v8::Undefined(); | 206 return v8::Undefined(); |
| 163 } | 207 } |
| 164 | 208 |
| 165 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value)); | 209 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value)); |
| 166 v8::Handle<v8::Value> exports(modules->Get(module_name)); | 210 v8::Handle<v8::Value> exports(modules->Get(module_name)); |
| 167 if (!exports->IsUndefined()) | 211 if (!exports->IsUndefined()) |
| 168 return handle_scope.Close(exports); | 212 return handle_scope.Close(exports); |
| 169 | 213 |
| 170 std::string module_name_str = *v8::String::AsciiValue(module_name); | 214 std::string module_name_str = *v8::String::AsciiValue(module_name); |
| 171 v8::Handle<v8::Value> source(GetSource(module_name_str)); | 215 v8::Handle<v8::Value> source(GetSource(module_name_str)); |
| 172 if (source.IsEmpty() || source->IsUndefined()) { | 216 if (source.IsEmpty() || source->IsUndefined()) { |
| 173 console::Error(v8::Context::GetCalling(), | 217 Fatal(context_->GetExtensionID(), |
| 174 "No source for require(" + module_name_str + ")"); | 218 "No source for require(" + module_name_str + ")"); |
| 175 return v8::Undefined(); | 219 return v8::Undefined(); |
| 176 } | 220 } |
| 177 v8::Handle<v8::String> wrapped_source(WrapSource( | 221 v8::Handle<v8::String> wrapped_source(WrapSource( |
| 178 v8::Handle<v8::String>::Cast(source))); | 222 v8::Handle<v8::String>::Cast(source))); |
| 179 // Modules are wrapped in (function(){...}) so they always return functions. | 223 // Modules are wrapped in (function(){...}) so they always return functions. |
| 180 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); | 224 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); |
| 181 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 225 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { |
| 182 console::Error(v8::Context::GetCalling(), | 226 Fatal(context_->GetExtensionID(), |
| 183 "Bad source for require(" + module_name_str + ")"); | 227 "Bad source for require(" + module_name_str + ")"); |
| 184 return v8::Undefined(); | 228 return v8::Undefined(); |
| 185 } | 229 } |
| 186 | 230 |
| 187 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 231 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); |
| 188 | 232 |
| 189 exports = v8::Object::New(); | 233 exports = v8::Object::New(); |
| 190 v8::Handle<v8::Object> natives(NewInstance()); | 234 v8::Handle<v8::Object> natives(NewInstance()); |
| 191 v8::Handle<v8::Value> args[] = { | 235 v8::Handle<v8::Value> args[] = { |
| 192 natives->Get(v8::String::NewSymbol("require")), | 236 natives->Get(v8::String::NewSymbol("require")), |
| 193 natives->Get(v8::String::NewSymbol("requireNative")), | 237 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()); | 279 v8::Context::Scope context_scope(context()->v8_context()); |
| 236 | 280 |
| 237 v8::Local<v8::Value> module; | 281 v8::Local<v8::Value> module; |
| 238 { | 282 { |
| 239 NativesEnabledScope natives_enabled(this); | 283 NativesEnabledScope natives_enabled(this); |
| 240 module = v8::Local<v8::Value>::New( | 284 module = v8::Local<v8::Value>::New( |
| 241 RequireForJsInner(v8::String::New(module_name.c_str()))); | 285 RequireForJsInner(v8::String::New(module_name.c_str()))); |
| 242 } | 286 } |
| 243 | 287 |
| 244 if (module.IsEmpty() || !module->IsObject()) { | 288 if (module.IsEmpty() || !module->IsObject()) { |
| 245 console::Error( | 289 Fatal(context_->GetExtensionID(), |
| 246 v8::Context::GetCalling(), | 290 "Failed to get module " + module_name + " to call " + method_name); |
| 247 "Failed to get module " + module_name + " to call " + method_name); | |
| 248 return handle_scope.Close(v8::Undefined()); | 291 return handle_scope.Close(v8::Undefined()); |
| 249 } | 292 } |
| 250 | 293 |
| 251 v8::Local<v8::Value> value = | 294 v8::Local<v8::Value> value = |
| 252 v8::Handle<v8::Object>::Cast(module)->Get( | 295 v8::Handle<v8::Object>::Cast(module)->Get( |
| 253 v8::String::New(method_name.c_str())); | 296 v8::String::New(method_name.c_str())); |
| 254 if (value.IsEmpty() || !value->IsFunction()) { | 297 if (value.IsEmpty() || !value->IsFunction()) { |
| 255 console::Error(v8::Context::GetCalling(), | 298 Fatal(context_->GetExtensionID(), |
| 256 module_name + "." + method_name + " is not a function"); | 299 module_name + "." + method_name + " is not a function"); |
| 257 return handle_scope.Close(v8::Undefined()); | 300 return handle_scope.Close(v8::Undefined()); |
| 258 } | 301 } |
| 259 | 302 |
| 260 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); | 303 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); |
| 261 v8::Local<v8::Value> result; | 304 v8::Local<v8::Value> result; |
| 262 { | 305 { |
| 263 v8::TryCatch try_catch; | 306 v8::TryCatch try_catch; |
| 264 try_catch.SetCaptureMessage(true); | 307 try_catch.SetCaptureMessage(true); |
| 265 result = context_->CallFunction(func, argc, argv); | 308 result = context_->CallFunction(func, argc, argv); |
| 266 if (try_catch.HasCaught()) | 309 if (try_catch.HasCaught()) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 v8::HandleScope handle_scope; | 353 v8::HandleScope handle_scope; |
| 311 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); | 354 v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); |
| 312 // This context should be the same as context()->v8_context(). | 355 // This context should be the same as context()->v8_context(). |
| 313 v8::Handle<v8::Context> context = parameters->CreationContext(); | 356 v8::Handle<v8::Context> context = parameters->CreationContext(); |
| 314 v8::Handle<v8::Object> global(context->Global()); | 357 v8::Handle<v8::Object> global(context->Global()); |
| 315 v8::Handle<v8::Value> module_system_value = | 358 v8::Handle<v8::Value> module_system_value = |
| 316 global->GetHiddenValue(v8::String::New(kModuleSystem)); | 359 global->GetHiddenValue(v8::String::New(kModuleSystem)); |
| 317 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { | 360 if (module_system_value.IsEmpty() || !module_system_value->IsExternal()) { |
| 318 // ModuleSystem has been deleted. | 361 // ModuleSystem has been deleted. |
| 319 // TODO(kalman): See comment in header file. | 362 // TODO(kalman): See comment in header file. |
| 320 console::Warn(v8::Context::GetCalling(), | 363 Warn("", "Module system has been deleted, does extension view exist?"); |
| 321 "Module system has been deleted, does extension view exist?"); | |
| 322 return; | 364 return; |
| 323 } | 365 } |
| 324 | 366 |
| 325 ModuleSystem* module_system = static_cast<ModuleSystem*>( | 367 ModuleSystem* module_system = static_cast<ModuleSystem*>( |
| 326 v8::Handle<v8::External>::Cast(module_system_value)->Value()); | 368 v8::Handle<v8::External>::Cast(module_system_value)->Value()); |
| 327 | 369 |
| 328 std::string name = *v8::String::AsciiValue( | 370 std::string name = *v8::String::AsciiValue( |
| 329 parameters->Get(v8::String::New(kModuleName))->ToString()); | 371 parameters->Get(v8::String::New(kModuleName))->ToString()); |
| 330 | 372 |
| 331 // Switch to our v8 context because we need functions created while running | 373 // 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. | 385 // require_function will have already logged this, we don't need to. |
| 344 return; | 386 return; |
| 345 } | 387 } |
| 346 | 388 |
| 347 v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast(module_value); | 389 v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast(module_value); |
| 348 v8::Handle<v8::String> field = | 390 v8::Handle<v8::String> field = |
| 349 parameters->Get(v8::String::New(kModuleField))->ToString(); | 391 parameters->Get(v8::String::New(kModuleField))->ToString(); |
| 350 | 392 |
| 351 if (!module->Has(field)) { | 393 if (!module->Has(field)) { |
| 352 std::string field_str = *v8::String::AsciiValue(field); | 394 std::string field_str = *v8::String::AsciiValue(field); |
| 353 console::Fatal(v8::Context::GetCalling(), | 395 Fatal(module_system->context_->GetExtensionID(), |
| 354 "Lazy require of " + name + "." + field_str + " did not " + | 396 "Lazy require of " + name + "." + field_str + " did not " + |
| 355 "set the " + field_str + " field"); | 397 "set the " + field_str + " field"); |
| 356 return; | 398 return; |
| 357 } | 399 } |
| 358 | 400 |
| 359 v8::Local<v8::Value> new_field = module->Get(field); | 401 v8::Local<v8::Value> new_field = module->Get(field); |
| 360 if (try_catch.HasCaught()) { | 402 if (try_catch.HasCaught()) { |
| 361 module_system->HandleException(try_catch); | 403 module_system->HandleException(try_catch); |
| 362 return; | 404 return; |
| 363 } | 405 } |
| 364 | 406 |
| 365 // Ok for it to be undefined, among other things it's how bindings signify | 407 // 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 } | 487 } |
| 446 | 488 |
| 447 v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( | 489 v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( |
| 448 const std::string& native_name) { | 490 const std::string& native_name) { |
| 449 if (natives_enabled_ == 0) { | 491 if (natives_enabled_ == 0) { |
| 450 // HACK: if in test throw exception so that we can test the natives-disabled | 492 // 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 | 493 // logic; however, under normal circumstances, this is programmer error so |
| 452 // we could crash. | 494 // we could crash. |
| 453 if (exception_handler_) | 495 if (exception_handler_) |
| 454 return v8::ThrowException(v8::String::New("Natives disabled")); | 496 return v8::ThrowException(v8::String::New("Natives disabled")); |
| 455 console::Fatal(v8::Context::GetCalling(), | 497 Fatal(context_->GetExtensionID(), |
| 456 "Natives disabled for requireNative(" + native_name + ")"); | 498 "Natives disabled for requireNative(" + native_name + ")"); |
| 457 return v8::Undefined(); | 499 return v8::Undefined(); |
| 458 } | 500 } |
| 459 | 501 |
| 460 if (overridden_native_handlers_.count(native_name) > 0u) | 502 if (overridden_native_handlers_.count(native_name) > 0u) |
| 461 return RequireForJsInner(v8::String::New(native_name.c_str())); | 503 return RequireForJsInner(v8::String::New(native_name.c_str())); |
| 462 | 504 |
| 463 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); | 505 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
| 464 if (i == native_handler_map_.end()) { | 506 if (i == native_handler_map_.end()) { |
| 465 console::Fatal( | 507 Fatal(context_->GetExtensionID(), |
| 466 v8::Context::GetCalling(), | 508 "Couldn't find native for requireNative(" + native_name + ")"); |
| 467 "Couldn't find native for requireNative(" + native_name + ")"); | |
| 468 return v8::Undefined(); | 509 return v8::Undefined(); |
| 469 } | 510 } |
| 470 return i->second->NewInstance(); | 511 return i->second->NewInstance(); |
| 471 } | 512 } |
| 472 | 513 |
| 473 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 514 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { |
| 474 v8::HandleScope handle_scope; | 515 v8::HandleScope handle_scope; |
| 475 v8::Handle<v8::String> left = v8::String::New( | 516 v8::Handle<v8::String> left = v8::String::New( |
| 476 "(function(require, requireNative, exports) {'use strict';"); | 517 "(function(require, requireNative, exports) {'use strict';"); |
| 477 v8::Handle<v8::String> right = v8::String::New("\n})"); | 518 v8::Handle<v8::String> right = v8::String::New("\n})"); |
| 478 return handle_scope.Close( | 519 return handle_scope.Close( |
| 479 v8::String::Concat(left, v8::String::Concat(source, right))); | 520 v8::String::Concat(left, v8::String::Concat(source, right))); |
| 480 } | 521 } |
| 481 | 522 |
| 482 } // namespace extensions | 523 } // namespace extensions |
| OLD | NEW |