| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/renderer/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 "content/public/renderer/render_view.h" | 13 #include "content/public/renderer/render_view.h" |
| 14 #include "extensions/common/extension_messages.h" | 14 #include "extensions/common/extension_messages.h" |
| 15 #include "extensions/common/extensions_client.h" | 15 #include "extensions/common/extensions_client.h" |
| 16 #include "extensions/renderer/console.h" | 16 #include "extensions/renderer/console.h" |
| 17 #include "extensions/renderer/safe_builtins.h" | 17 #include "extensions/renderer/safe_builtins.h" |
| 18 #include "extensions/renderer/script_context.h" | 18 #include "extensions/renderer/script_context.h" |
| 19 #include "gin/modules/module_registry.h" |
| 19 #include "third_party/WebKit/public/web/WebFrame.h" | 20 #include "third_party/WebKit/public/web/WebFrame.h" |
| 20 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" | 21 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" |
| 21 | 22 |
| 22 namespace extensions { | 23 namespace extensions { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 const char* kModuleSystem = "module_system"; | 27 const char* kModuleSystem = "module_system"; |
| 27 const char* kModuleName = "module_name"; | 28 const char* kModuleName = "module_name"; |
| 28 const char* kModuleField = "module_field"; | 29 const char* kModuleField = "module_field"; |
| 29 const char* kModulesField = "modules"; | |
| 30 | 30 |
| 31 // 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 |
| 32 // the context: | 32 // the context: |
| 33 // - Its type (blessed, unblessed, etc). | 33 // - Its type (blessed, unblessed, etc). |
| 34 // - Whether it's valid. | 34 // - Whether it's valid. |
| 35 // - The extension ID, if one exists. | 35 // - The extension ID, if one exists. |
| 36 // | 36 // |
| 37 // 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 |
| 38 // 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 |
| 39 // 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 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 "require", | 126 "require", |
| 127 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 127 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
| 128 RouteFunction( | 128 RouteFunction( |
| 129 "requireNative", | 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(v8::String::NewFromUtf8(isolate, kModulesField), | |
| 137 v8::Object::New(isolate)); | |
| 138 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), | 136 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), |
| 139 v8::External::New(isolate, this)); | 137 v8::External::New(isolate, this)); |
| 138 |
| 139 gin::ModuleRegistry* registry = |
| 140 gin::ModuleRegistry::From(context->v8_context()); |
| 141 DCHECK(registry); |
| 142 registry->AddObserver(this); |
| 143 registry->AddBuiltinModule( |
| 144 GetIsolate(), "array", context->safe_builtins()->GetArray()); |
| 145 registry->AddBuiltinModule(GetIsolate(), "console", console::AsV8Object()); |
| 146 registry->AddBuiltinModule( |
| 147 GetIsolate(), "function", context->safe_builtins()->GetFunction()); |
| 148 registry->AddBuiltinModule( |
| 149 GetIsolate(), "json", context->safe_builtins()->GetJSON()); |
| 150 registry->AddBuiltinModule( |
| 151 GetIsolate(), "object", context->safe_builtins()->GetObjekt()); |
| 152 registry->AddBuiltinModule( |
| 153 GetIsolate(), "regexp", context->safe_builtins()->GetRegExp()); |
| 154 registry->AddBuiltinModule( |
| 155 GetIsolate(), "string", context->safe_builtins()->GetString()); |
| 156 v8::Handle<v8::Object> natives(NewInstance()); |
| 157 registry->AddBuiltinModule( |
| 158 GetIsolate(), |
| 159 "require", |
| 160 natives->Get(v8::String::NewFromUtf8( |
| 161 GetIsolate(), "require", v8::String::kInternalizedString))); |
| 162 registry->AddBuiltinModule( |
| 163 GetIsolate(), |
| 164 "requireNative", |
| 165 natives->Get(v8::String::NewFromUtf8( |
| 166 GetIsolate(), "requireNative", v8::String::kInternalizedString))); |
| 167 registry->AddBuiltinModule( |
| 168 GetIsolate(), |
| 169 "privates", |
| 170 natives->Get(v8::String::NewFromUtf8( |
| 171 GetIsolate(), "privates", v8::String::kInternalizedString))); |
| 172 |
| 173 modules_supporting_amd_.insert("app.runtime"); |
| 174 modules_supporting_amd_.insert("entryIdManager"); |
| 140 } | 175 } |
| 141 | 176 |
| 142 ModuleSystem::~ModuleSystem() { Invalidate(); } | 177 ModuleSystem::~ModuleSystem() { Invalidate(); } |
| 143 | 178 |
| 144 void ModuleSystem::Invalidate() { | 179 void ModuleSystem::Invalidate() { |
| 145 if (!is_valid()) | 180 if (!is_valid()) |
| 146 return; | 181 return; |
| 147 | 182 |
| 148 // Clear the module system properties from the global context. It's polite, | 183 // Clear the module system properties from the global context. It's polite, |
| 149 // and we use this as a signal in lazy handlers that we no longer exist. | 184 // and we use this as a signal in lazy handlers that we no longer exist. |
| 150 { | 185 { |
| 151 v8::HandleScope scope(GetIsolate()); | 186 v8::HandleScope scope(GetIsolate()); |
| 152 v8::Handle<v8::Object> global = context()->v8_context()->Global(); | 187 v8::Handle<v8::Object> global = context()->v8_context()->Global(); |
| 153 global->DeleteHiddenValue( | 188 global->DeleteHiddenValue( |
| 154 v8::String::NewFromUtf8(GetIsolate(), kModulesField)); | |
| 155 global->DeleteHiddenValue( | |
| 156 v8::String::NewFromUtf8(GetIsolate(), kModuleSystem)); | 189 v8::String::NewFromUtf8(GetIsolate(), kModuleSystem)); |
| 157 } | 190 } |
| 158 | 191 |
| 159 // Invalidate all of the successfully required handlers we own. | 192 // Invalidate all of the successfully required handlers we own. |
| 160 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); | 193 for (NativeHandlerMap::iterator it = native_handler_map_.begin(); |
| 161 it != native_handler_map_.end(); | 194 it != native_handler_map_.end(); |
| 162 ++it) { | 195 ++it) { |
| 163 it->second->Invalidate(); | 196 it->second->Invalidate(); |
| 164 } | 197 } |
| 165 | 198 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 191 const v8::FunctionCallbackInfo<v8::Value>& args) { | 224 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 192 v8::Handle<v8::String> module_name = args[0]->ToString(); | 225 v8::Handle<v8::String> module_name = args[0]->ToString(); |
| 193 args.GetReturnValue().Set(RequireForJsInner(module_name)); | 226 args.GetReturnValue().Set(RequireForJsInner(module_name)); |
| 194 } | 227 } |
| 195 | 228 |
| 196 v8::Local<v8::Value> ModuleSystem::RequireForJsInner( | 229 v8::Local<v8::Value> ModuleSystem::RequireForJsInner( |
| 197 v8::Handle<v8::String> module_name) { | 230 v8::Handle<v8::String> module_name) { |
| 198 v8::EscapableHandleScope handle_scope(GetIsolate()); | 231 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 199 v8::Context::Scope context_scope(context()->v8_context()); | 232 v8::Context::Scope context_scope(context()->v8_context()); |
| 200 | 233 |
| 201 v8::Handle<v8::Object> global(context()->v8_context()->Global()); | 234 std::string module_name_str = |
| 202 | 235 std::string(*v8::String::Utf8Value(module_name)); |
| 203 // The module system might have been deleted. This can happen if a different | 236 gin::ModuleRegistry* registry = |
| 204 // context keeps a reference to us, but our frame is destroyed (e.g. | 237 gin::ModuleRegistry::From(context()->v8_context()); |
| 205 // background page keeps reference to chrome object in a closed popup). | 238 if (!registry) { |
| 206 v8::Handle<v8::Value> modules_value = global->GetHiddenValue( | 239 return handle_scope.Escape( |
| 207 v8::String::NewFromUtf8(GetIsolate(), kModulesField)); | 240 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); |
| 208 if (modules_value.IsEmpty() || modules_value->IsUndefined()) { | |
| 209 Warn(GetIsolate(), "Extension view no longer exists"); | |
| 210 return v8::Undefined(GetIsolate()); | |
| 211 } | 241 } |
| 212 | 242 |
| 213 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value)); | 243 if (registry->available_modules().count(module_name_str) == 0 && |
| 214 v8::Local<v8::Value> exports(modules->Get(module_name)); | 244 !LoadModule(module_name_str)) { |
| 215 if (!exports->IsUndefined()) | 245 return handle_scope.Escape( |
| 216 return handle_scope.Escape(exports); | 246 v8::Local<v8::Primitive>(v8::Undefined(GetIsolate()))); |
| 247 } |
| 248 return handle_scope.Escape( |
| 249 v8::Local<v8::Value>(registry->GetModule(GetIsolate(), module_name_str))); |
| 250 } |
| 217 | 251 |
| 218 std::string module_name_str = *v8::String::Utf8Value(module_name); | 252 bool ModuleSystem::LoadModule(const std::string& module_name) { |
| 219 v8::Handle<v8::Value> source(GetSource(module_name_str)); | 253 if (failed_module_loads_.count(module_name) != 0) |
| 254 return false; |
| 255 |
| 256 gin::ModuleRegistry* registry = |
| 257 gin::ModuleRegistry::From(context()->v8_context()); |
| 258 DCHECK_EQ(0u, registry->available_modules().count(module_name)); |
| 259 v8::HandleScope handle_scope(GetIsolate()); |
| 260 v8::Context::Scope context_scope(context()->v8_context()); |
| 261 |
| 262 if (LoadNative(module_name)) |
| 263 return true; |
| 264 |
| 265 v8::Handle<v8::Value> source(GetSource(module_name)); |
| 220 if (source.IsEmpty() || source->IsUndefined()) { | 266 if (source.IsEmpty() || source->IsUndefined()) { |
| 221 Fatal(context_, "No source for require(" + module_name_str + ")"); | 267 Fatal(context_, "No source for module " + module_name); |
| 222 return v8::Undefined(GetIsolate()); | 268 return false; |
| 223 } | 269 } |
| 224 v8::Handle<v8::String> wrapped_source( | 270 v8::Handle<v8::String> wrapped_source( |
| 225 WrapSource(v8::Handle<v8::String>::Cast(source))); | 271 WrapSource(v8::Handle<v8::String>::Cast(source), module_name)); |
| 226 // Modules are wrapped in (function(){...}) so they always return functions. | 272 // Modules are wrapped in (function(){...}) so they always return functions. |
| 227 v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); | 273 v8::Handle<v8::String> module_name_js( |
| 274 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); |
| 275 v8::Handle<v8::Value> func_as_value = |
| 276 RunString(wrapped_source, module_name_js); |
| 228 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 277 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { |
| 229 Fatal(context_, "Bad source for require(" + module_name_str + ")"); | 278 Fatal(context_, "Bad source for module " + module_name); |
| 230 return v8::Undefined(GetIsolate()); | 279 return false; |
| 231 } | 280 } |
| 232 | 281 |
| 233 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 282 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); |
| 234 | 283 |
| 235 exports = v8::Object::New(GetIsolate()); | 284 v8::Handle<v8::Object> define_object = v8::Object::New(GetIsolate()); |
| 236 v8::Handle<v8::Object> natives(NewInstance()); | 285 gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object); |
| 237 CHECK(!natives.IsEmpty()); // this can happen if v8 has issues | |
| 238 | 286 |
| 239 // These must match the argument order in WrapSource. | 287 // These must match the argument order in WrapAmdSource. |
| 240 v8::Handle<v8::Value> args[] = { | 288 v8::Handle<v8::Value> args[] = { |
| 241 // CommonJS. | 289 define_object->Get(v8::String::NewFromUtf8(GetIsolate(), "define")), |
| 242 natives->Get(v8::String::NewFromUtf8( | 290 }; |
| 243 GetIsolate(), "require", v8::String::kInternalizedString)), | |
| 244 natives->Get(v8::String::NewFromUtf8( | |
| 245 GetIsolate(), "requireNative", v8::String::kInternalizedString)), | |
| 246 exports, | |
| 247 // Libraries that we magically expose to every module. | |
| 248 console::AsV8Object(), | |
| 249 natives->Get(v8::String::NewFromUtf8( | |
| 250 GetIsolate(), "privates", v8::String::kInternalizedString)), | |
| 251 // Each safe builtin. Keep in order with the arguments in WrapSource. | |
| 252 context_->safe_builtins()->GetArray(), | |
| 253 context_->safe_builtins()->GetFunction(), | |
| 254 context_->safe_builtins()->GetJSON(), | |
| 255 context_->safe_builtins()->GetObjekt(), | |
| 256 context_->safe_builtins()->GetRegExp(), | |
| 257 context_->safe_builtins()->GetString(), }; | |
| 258 { | 291 { |
| 259 v8::TryCatch try_catch; | 292 v8::TryCatch try_catch; |
| 260 try_catch.SetCaptureMessage(true); | 293 try_catch.SetCaptureMessage(true); |
| 261 context_->CallFunction(func, arraysize(args), args); | 294 context_->CallFunction(func, arraysize(args), args); |
| 262 if (try_catch.HasCaught()) { | 295 if (try_catch.HasCaught()) |
| 263 HandleException(try_catch); | 296 HandleException(try_catch); |
| 264 return v8::Undefined(GetIsolate()); | |
| 265 } | |
| 266 } | 297 } |
| 267 modules->Set(module_name, exports); | 298 if (registry->available_modules().count(module_name) == 0) { |
| 268 return handle_scope.Escape(exports); | 299 failed_module_loads_.insert(module_name); |
| 300 return false; |
| 301 } |
| 302 return true; |
| 303 } |
| 304 |
| 305 bool ModuleSystem::LoadNative(const std::string& native_name) { |
| 306 if (natives_enabled_ == 0) |
| 307 return false; |
| 308 |
| 309 v8::HandleScope scope(GetIsolate()); |
| 310 gin::ModuleRegistry* registry = |
| 311 gin::ModuleRegistry::From(context_->v8_context()); |
| 312 if (overridden_native_handlers_.count(native_name) > 0u) |
| 313 return false; |
| 314 |
| 315 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
| 316 if (i == native_handler_map_.end()) { |
| 317 return false; |
| 318 } |
| 319 |
| 320 registry->AddBuiltinModule( |
| 321 GetIsolate(), native_name, i->second->NewInstance()); |
| 322 return true; |
| 323 } |
| 324 |
| 325 void ModuleSystem::OnDidAddPendingModule( |
| 326 const std::string& id, |
| 327 const std::vector<std::string>& dependencies) { |
| 328 if (!source_map_->Contains(id)) |
| 329 return; |
| 330 |
| 331 gin::ModuleRegistry* registry = |
| 332 gin::ModuleRegistry::From(context_->v8_context()); |
| 333 for (std::vector<std::string>::const_iterator it = dependencies.begin(); |
| 334 it != dependencies.end(); |
| 335 ++it) { |
| 336 if (registry->available_modules().count(*it) != 0) |
| 337 continue; |
| 338 |
| 339 if (!LoadModule(*it)) |
| 340 LOG(DFATAL) << "Invalid dependency " << *it << " in module " << id; |
| 341 } |
| 342 gin::ModuleRegistry::From(context_->v8_context()) |
| 343 ->AttemptToLoadMoreModules(GetIsolate()); |
| 269 } | 344 } |
| 270 | 345 |
| 271 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( | 346 v8::Local<v8::Value> ModuleSystem::CallModuleMethod( |
| 272 const std::string& module_name, | 347 const std::string& module_name, |
| 273 const std::string& method_name) { | 348 const std::string& method_name) { |
| 274 v8::HandleScope handle_scope(GetIsolate()); | 349 v8::HandleScope handle_scope(GetIsolate()); |
| 275 v8::Handle<v8::Value> no_args; | 350 v8::Handle<v8::Value> no_args; |
| 276 return CallModuleMethod(module_name, method_name, 0, &no_args); | 351 return CallModuleMethod(module_name, method_name, 0, &no_args); |
| 277 } | 352 } |
| 278 | 353 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 // HACK: if in test throw exception so that we can test the natives-disabled | 611 // HACK: if in test throw exception so that we can test the natives-disabled |
| 537 // logic; however, under normal circumstances, this is programmer error so | 612 // logic; however, under normal circumstances, this is programmer error so |
| 538 // we could crash. | 613 // we could crash. |
| 539 if (exception_handler_) { | 614 if (exception_handler_) { |
| 540 return GetIsolate()->ThrowException( | 615 return GetIsolate()->ThrowException( |
| 541 v8::String::NewFromUtf8(GetIsolate(), "Natives disabled")); | 616 v8::String::NewFromUtf8(GetIsolate(), "Natives disabled")); |
| 542 } | 617 } |
| 543 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")"); | 618 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")"); |
| 544 return v8::Undefined(GetIsolate()); | 619 return v8::Undefined(GetIsolate()); |
| 545 } | 620 } |
| 621 gin::ModuleRegistry* registry = |
| 622 gin::ModuleRegistry::From(context()->v8_context()); |
| 623 if (!registry) |
| 624 return v8::Undefined(GetIsolate()); |
| 546 | 625 |
| 547 if (overridden_native_handlers_.count(native_name) > 0u) { | 626 if (registry->available_modules().count(native_name) == 0 && |
| 548 return RequireForJsInner( | 627 !LoadModule(native_name)) { |
| 549 v8::String::NewFromUtf8(GetIsolate(), native_name.c_str())); | |
| 550 } | |
| 551 | |
| 552 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); | |
| 553 if (i == native_handler_map_.end()) { | |
| 554 Fatal(context_, | 628 Fatal(context_, |
| 555 "Couldn't find native for requireNative(" + native_name + ")"); | 629 "Couldn't find native for requireNative(" + native_name + ")"); |
| 556 return v8::Undefined(GetIsolate()); | 630 return v8::Undefined(GetIsolate()); |
| 557 } | 631 } |
| 558 return i->second->NewInstance(); | 632 return registry->GetModule(GetIsolate(), native_name); |
| 559 } | 633 } |
| 560 | 634 |
| 561 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 635 v8::Handle<v8::String> ModuleSystem::WrapSource( |
| 636 v8::Handle<v8::String> source, |
| 637 const std::string& module_name) { |
| 638 if (modules_supporting_amd_.count(module_name) != 0 || |
| 639 module_name.find('/') != std::string::npos) { |
| 640 return WrapAmdSource(source); |
| 641 } |
| 642 |
| 562 v8::EscapableHandleScope handle_scope(GetIsolate()); | 643 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 563 // Keep in order with the arguments in RequireForJsInner. | 644 v8::Handle<v8::String> left = |
| 564 v8::Handle<v8::String> left = v8::String::NewFromUtf8( | 645 v8::String::NewFromUtf8(GetIsolate(), |
| 565 GetIsolate(), | 646 ("define('" + module_name + |
| 566 "(function(require, requireNative, exports, " | 647 "', [" |
| 567 "console, privates," | 648 "'require'," |
| 568 "$Array, $Function, $JSON, $Object, $RegExp, $String) {" | 649 "'requireNative'," |
| 569 "'use strict';"); | 650 "'privates'," |
| 651 "'array'," |
| 652 "'function'," |
| 653 "'json'," |
| 654 "'object'," |
| 655 "'regexp'," |
| 656 "'string'," |
| 657 "'console'," |
| 658 "], function(require, requireNative, privates, " |
| 659 "$Array, $Function, $JSON, " |
| 660 "$Object, $RegExp, $String, console) {" |
| 661 "var exports = {};").c_str()); |
| 662 v8::Handle<v8::String> right = |
| 663 v8::String::NewFromUtf8(GetIsolate(), "\nreturn exports;})"); |
| 664 return handle_scope.Escape(v8::Local<v8::String>(WrapAmdSource( |
| 665 v8::String::Concat(left, v8::String::Concat(source, right))))); |
| 666 } |
| 667 |
| 668 v8::Handle<v8::String> ModuleSystem::WrapAmdSource( |
| 669 v8::Handle<v8::String> source) { |
| 670 v8::EscapableHandleScope handle_scope(GetIsolate()); |
| 671 // Keep in order with the arguments in LoadModule. |
| 672 v8::Handle<v8::String> left = |
| 673 v8::String::NewFromUtf8(GetIsolate(), "(function(define) {'use strict';"); |
| 570 v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})"); | 674 v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})"); |
| 571 return handle_scope.Escape(v8::Local<v8::String>( | 675 return handle_scope.Escape(v8::Local<v8::String>( |
| 572 v8::String::Concat(left, v8::String::Concat(source, right)))); | 676 v8::String::Concat(left, v8::String::Concat(source, right)))); |
| 573 } | 677 } |
| 574 | 678 |
| 575 void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) { | 679 void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 576 CHECK_EQ(1, args.Length()); | 680 CHECK_EQ(1, args.Length()); |
| 577 CHECK(args[0]->IsObject()); | 681 CHECK(args[0]->IsObject()); |
| 578 v8::Local<v8::Object> obj = args[0].As<v8::Object>(); | 682 v8::Local<v8::Object> obj = args[0].As<v8::Object>(); |
| 579 v8::Local<v8::String> privates_key = | 683 v8::Local<v8::String> privates_key = |
| 580 v8::String::NewFromUtf8(GetIsolate(), "privates"); | 684 v8::String::NewFromUtf8(GetIsolate(), "privates"); |
| 581 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); | 685 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); |
| 582 if (privates.IsEmpty()) { | 686 if (privates.IsEmpty()) { |
| 583 privates = v8::Object::New(args.GetIsolate()); | 687 privates = v8::Object::New(args.GetIsolate()); |
| 584 obj->SetHiddenValue(privates_key, privates); | 688 obj->SetHiddenValue(privates_key, privates); |
| 585 } | 689 } |
| 586 args.GetReturnValue().Set(privates); | 690 args.GetReturnValue().Set(privates); |
| 587 } | 691 } |
| 588 | 692 |
| 589 } // namespace extensions | 693 } // namespace extensions |
| OLD | NEW |