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"; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 resource_name.c_str(), | 115 resource_name.c_str(), |
115 message->GetLineNumber(), | 116 message->GetLineNumber(), |
116 error_message.c_str()); | 117 error_message.c_str()); |
117 } | 118 } |
118 | 119 |
119 ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map) | 120 ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map) |
120 : ObjectBackedNativeHandler(context), | 121 : ObjectBackedNativeHandler(context), |
121 context_(context), | 122 context_(context), |
122 source_map_(source_map), | 123 source_map_(source_map), |
123 natives_enabled_(0), | 124 natives_enabled_(0), |
124 exception_handler_(new DefaultExceptionHandler(context)) { | 125 exception_handler_(new DefaultExceptionHandler(context)), |
126 weak_factory_(this) { | |
125 RouteFunction( | 127 RouteFunction( |
126 "require", | 128 "require", |
127 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 129 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); |
128 RouteFunction( | 130 RouteFunction( |
129 "requireNative", | 131 "requireNative", |
130 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); | 132 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); |
133 RouteFunction( | |
134 "requireAsync", | |
135 base::Bind(&ModuleSystem::RequireAsync, base::Unretained(this))); | |
131 RouteFunction("privates", | 136 RouteFunction("privates", |
132 base::Bind(&ModuleSystem::Private, base::Unretained(this))); | 137 base::Bind(&ModuleSystem::Private, base::Unretained(this))); |
133 | 138 |
134 v8::Handle<v8::Object> global(context->v8_context()->Global()); | 139 v8::Handle<v8::Object> global(context->v8_context()->Global()); |
135 v8::Isolate* isolate = context->isolate(); | 140 v8::Isolate* isolate = context->isolate(); |
136 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModulesField), | 141 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModulesField), |
137 v8::Object::New(isolate)); | 142 v8::Object::New(isolate)); |
138 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), | 143 global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), |
139 v8::External::New(isolate, this)); | 144 v8::External::New(isolate, this)); |
145 | |
146 gin::ModuleRegistry::From(context->v8_context())->AddObserver(this); | |
140 } | 147 } |
141 | 148 |
142 ModuleSystem::~ModuleSystem() { Invalidate(); } | 149 ModuleSystem::~ModuleSystem() { Invalidate(); } |
143 | 150 |
144 void ModuleSystem::Invalidate() { | 151 void ModuleSystem::Invalidate() { |
145 if (!is_valid()) | 152 if (!is_valid()) |
146 return; | 153 return; |
147 | 154 |
148 // Clear the module system properties from the global context. It's polite, | 155 // 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. | 156 // and we use this as a signal in lazy handlers that we no longer exist. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 v8::Handle<v8::Object> natives(NewInstance()); | 243 v8::Handle<v8::Object> natives(NewInstance()); |
237 CHECK(!natives.IsEmpty()); // this can happen if v8 has issues | 244 CHECK(!natives.IsEmpty()); // this can happen if v8 has issues |
238 | 245 |
239 // These must match the argument order in WrapSource. | 246 // These must match the argument order in WrapSource. |
240 v8::Handle<v8::Value> args[] = { | 247 v8::Handle<v8::Value> args[] = { |
241 // CommonJS. | 248 // CommonJS. |
242 natives->Get(v8::String::NewFromUtf8( | 249 natives->Get(v8::String::NewFromUtf8( |
243 GetIsolate(), "require", v8::String::kInternalizedString)), | 250 GetIsolate(), "require", v8::String::kInternalizedString)), |
244 natives->Get(v8::String::NewFromUtf8( | 251 natives->Get(v8::String::NewFromUtf8( |
245 GetIsolate(), "requireNative", v8::String::kInternalizedString)), | 252 GetIsolate(), "requireNative", v8::String::kInternalizedString)), |
253 natives->Get(v8::String::NewFromUtf8( | |
254 GetIsolate(), "requireAsync", v8::String::kInternalizedString)), | |
246 exports, | 255 exports, |
247 // Libraries that we magically expose to every module. | 256 // Libraries that we magically expose to every module. |
248 console::AsV8Object(), | 257 console::AsV8Object(), |
249 natives->Get(v8::String::NewFromUtf8( | 258 natives->Get(v8::String::NewFromUtf8( |
250 GetIsolate(), "privates", v8::String::kInternalizedString)), | 259 GetIsolate(), "privates", v8::String::kInternalizedString)), |
251 // Each safe builtin. Keep in order with the arguments in WrapSource. | 260 // Each safe builtin. Keep in order with the arguments in WrapSource. |
252 context_->safe_builtins()->GetArray(), | 261 context_->safe_builtins()->GetArray(), |
253 context_->safe_builtins()->GetFunction(), | 262 context_->safe_builtins()->GetFunction(), |
254 context_->safe_builtins()->GetJSON(), | 263 context_->safe_builtins()->GetJSON(), |
255 context_->safe_builtins()->GetObjekt(), | 264 context_->safe_builtins()->GetObjekt(), |
256 context_->safe_builtins()->GetRegExp(), | 265 context_->safe_builtins()->GetRegExp(), |
257 context_->safe_builtins()->GetString(), }; | 266 context_->safe_builtins()->GetString(), |
not at google - send to devlin
2014/07/01 18:13:05
btw this was git cl format being a pain, which is
Sam McNally
2014/07/02 03:26:35
I think clang format prefers this formatting now.
| |
267 }; | |
258 { | 268 { |
259 v8::TryCatch try_catch; | 269 v8::TryCatch try_catch; |
260 try_catch.SetCaptureMessage(true); | 270 try_catch.SetCaptureMessage(true); |
261 context_->CallFunction(func, arraysize(args), args); | 271 context_->CallFunction(func, arraysize(args), args); |
262 if (try_catch.HasCaught()) { | 272 if (try_catch.HasCaught()) { |
263 HandleException(try_catch); | 273 HandleException(try_catch); |
264 return v8::Undefined(GetIsolate()); | 274 return v8::Undefined(GetIsolate()); |
265 } | 275 } |
266 } | 276 } |
267 modules->Set(module_name, exports); | 277 modules->Set(module_name, exports); |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 | 561 |
552 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); | 562 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); |
553 if (i == native_handler_map_.end()) { | 563 if (i == native_handler_map_.end()) { |
554 Fatal(context_, | 564 Fatal(context_, |
555 "Couldn't find native for requireNative(" + native_name + ")"); | 565 "Couldn't find native for requireNative(" + native_name + ")"); |
556 return v8::Undefined(GetIsolate()); | 566 return v8::Undefined(GetIsolate()); |
557 } | 567 } |
558 return i->second->NewInstance(); | 568 return i->second->NewInstance(); |
559 } | 569 } |
560 | 570 |
571 void ModuleSystem::RequireAsync( | |
572 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
573 CHECK_EQ(1, args.Length()); | |
574 std::string module_name = *v8::String::Utf8Value(args[0]->ToString()); | |
575 v8::Handle<v8::Promise::Resolver> resolver( | |
576 v8::Promise::Resolver::New(GetIsolate())); | |
577 v8::Handle<v8::Promise> promise(resolver->GetPromise()); | |
578 scoped_ptr<v8::UniquePersistent<v8::Promise::Resolver> > persistent_resolver( | |
579 new v8::UniquePersistent<v8::Promise::Resolver>(GetIsolate(), resolver)); | |
580 gin::ModuleRegistry* module_registry = | |
581 gin::ModuleRegistry::From(context_->v8_context()); | |
582 module_registry->LoadModule(GetIsolate(), | |
583 module_name, | |
584 base::Bind(&ModuleSystem::OnModuleLoaded, | |
585 weak_factory_.GetWeakPtr(), | |
586 base::Passed(&persistent_resolver))); | |
587 args.GetReturnValue().Set(promise); | |
588 if (module_registry->available_modules().count(module_name) == 0) | |
589 LoadAmdModule(module_name); | |
590 } | |
591 | |
561 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 592 v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { |
562 v8::EscapableHandleScope handle_scope(GetIsolate()); | 593 v8::EscapableHandleScope handle_scope(GetIsolate()); |
563 // Keep in order with the arguments in RequireForJsInner. | 594 // Keep in order with the arguments in RequireForJsInner. |
564 v8::Handle<v8::String> left = v8::String::NewFromUtf8( | 595 v8::Handle<v8::String> left = v8::String::NewFromUtf8( |
565 GetIsolate(), | 596 GetIsolate(), |
566 "(function(require, requireNative, exports, " | 597 "(function(require, requireNative, requireAsync, exports, " |
567 "console, privates," | 598 "console, privates," |
568 "$Array, $Function, $JSON, $Object, $RegExp, $String) {" | 599 "$Array, $Function, $JSON, $Object, $RegExp, $String) {" |
569 "'use strict';"); | 600 "'use strict';"); |
570 v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})"); | 601 v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})"); |
571 return handle_scope.Escape(v8::Local<v8::String>( | 602 return handle_scope.Escape(v8::Local<v8::String>( |
572 v8::String::Concat(left, v8::String::Concat(source, right)))); | 603 v8::String::Concat(left, v8::String::Concat(source, right)))); |
573 } | 604 } |
574 | 605 |
606 v8::Handle<v8::String> ModuleSystem::WrapAmdSource( | |
607 v8::Handle<v8::String> source) { | |
608 v8::EscapableHandleScope handle_scope(GetIsolate()); | |
609 // Keep in order with the arguments in LoadAmdModule. | |
610 v8::Handle<v8::String> left = | |
611 v8::String::NewFromUtf8(GetIsolate(), "(function(define) {"); | |
612 v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})"); | |
613 return handle_scope.Escape(v8::Local<v8::String>( | |
614 v8::String::Concat(left, v8::String::Concat(source, right)))); | |
615 } | |
616 | |
575 void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) { | 617 void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) { |
576 CHECK_EQ(1, args.Length()); | 618 CHECK_EQ(1, args.Length()); |
577 CHECK(args[0]->IsObject()); | 619 CHECK(args[0]->IsObject()); |
578 v8::Local<v8::Object> obj = args[0].As<v8::Object>(); | 620 v8::Local<v8::Object> obj = args[0].As<v8::Object>(); |
579 v8::Local<v8::String> privates_key = | 621 v8::Local<v8::String> privates_key = |
580 v8::String::NewFromUtf8(GetIsolate(), "privates"); | 622 v8::String::NewFromUtf8(GetIsolate(), "privates"); |
581 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); | 623 v8::Local<v8::Value> privates = obj->GetHiddenValue(privates_key); |
582 if (privates.IsEmpty()) { | 624 if (privates.IsEmpty()) { |
583 privates = v8::Object::New(args.GetIsolate()); | 625 privates = v8::Object::New(args.GetIsolate()); |
584 obj->SetHiddenValue(privates_key, privates); | 626 obj->SetHiddenValue(privates_key, privates); |
585 } | 627 } |
586 args.GetReturnValue().Set(privates); | 628 args.GetReturnValue().Set(privates); |
587 } | 629 } |
588 | 630 |
631 void ModuleSystem::LoadAmdModule(const std::string& module_name) { | |
632 v8::HandleScope handle_scope(GetIsolate()); | |
633 v8::Context::Scope context_scope(context()->v8_context()); | |
634 | |
635 v8::Handle<v8::Value> source(GetSource(module_name)); | |
636 if (source.IsEmpty() || source->IsUndefined()) { | |
637 Fatal(context_, "No source for requireAsync(" + module_name + ")"); | |
638 return; | |
639 } | |
640 v8::Handle<v8::String> wrapped_source( | |
641 WrapAmdSource(v8::Handle<v8::String>::Cast(source))); | |
642 // Modules are wrapped in (function(){...}) so they always return functions. | |
643 v8::Handle<v8::Value> func_as_value = | |
644 RunString(wrapped_source, | |
645 v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); | |
646 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | |
647 Fatal(context_, "Bad source for requireAsync(" + module_name + ")"); | |
648 return; | |
649 } | |
not at google - send to devlin
2014/07/01 18:13:05
surely there is some code we can share with the sy
Sam McNally
2014/07/02 03:26:35
Done.
| |
650 | |
651 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | |
652 | |
653 v8::Handle<v8::Object> define_object = v8::Object::New(GetIsolate()); | |
654 gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object); | |
655 | |
656 // These must match the argument order in WrapAmdSource. | |
657 v8::Handle<v8::Value> args[] = { | |
658 define_object->Get(v8::String::NewFromUtf8(GetIsolate(), "define")), | |
659 }; | |
660 { | |
661 v8::TryCatch try_catch; | |
662 try_catch.SetCaptureMessage(true); | |
663 context_->CallFunction(func, arraysize(args), args); | |
664 if (try_catch.HasCaught()) { | |
665 HandleException(try_catch); | |
666 return; | |
667 } | |
668 } | |
669 } | |
670 | |
671 void ModuleSystem::OnDidAddPendingModule( | |
672 const std::string& id, | |
673 const std::vector<std::string>& dependencies) { | |
674 if (!source_map_->Contains(id)) | |
675 return; | |
676 | |
677 gin::ModuleRegistry* registry = | |
678 gin::ModuleRegistry::From(context_->v8_context()); | |
679 for (std::vector<std::string>::const_iterator it = dependencies.begin(); | |
680 it != dependencies.end(); | |
681 ++it) { | |
682 if (registry->available_modules().count(*it) == 0) | |
683 LoadAmdModule(*it); | |
684 } | |
685 registry->AttemptToLoadMoreModules(GetIsolate()); | |
686 } | |
687 | |
688 void ModuleSystem::OnModuleLoaded( | |
689 scoped_ptr<v8::UniquePersistent<v8::Promise::Resolver> > resolver, | |
690 v8::Handle<v8::Value> value) { | |
691 v8::HandleScope handle_scope(GetIsolate()); | |
692 v8::Handle<v8::Promise::Resolver> resolver_local( | |
693 v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver)); | |
not at google - send to devlin
2014/07/01 18:13:05
you should also check is_valid(). the C++ lifetime
Sam McNally
2014/07/02 03:26:35
Done.
| |
694 resolver_local->Resolve(value); | |
695 } | |
696 | |
589 } // namespace extensions | 697 } // namespace extensions |
OLD | NEW |