Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1008)

Side by Side Diff: extensions/renderer/module_system.cc

Issue 359413004: Add support for using AMD modules from extensions modules. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698