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

Unified Diff: extensions/renderer/module_system.cc

Issue 302463005: Add support for AMD to the extensions module system. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « extensions/renderer/module_system.h ('k') | extensions/renderer/resources/app_runtime_custom_bindings.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/module_system.cc
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc
index a10fabd350e406b443a4a963fd42ebfd57325570..553b7f8e412bce36ad91449333e7c5770aedea37 100644
--- a/extensions/renderer/module_system.cc
+++ b/extensions/renderer/module_system.cc
@@ -16,6 +16,7 @@
#include "extensions/renderer/console.h"
#include "extensions/renderer/safe_builtins.h"
#include "extensions/renderer/script_context.h"
+#include "gin/modules/module_registry.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
@@ -26,7 +27,6 @@ namespace {
const char* kModuleSystem = "module_system";
const char* kModuleName = "module_name";
const char* kModuleField = "module_field";
-const char* kModulesField = "modules";
// Logs a fatal error for the calling context, with some added metadata about
// the context:
@@ -133,10 +133,45 @@ ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map)
v8::Handle<v8::Object> global(context->v8_context()->Global());
v8::Isolate* isolate = context->isolate();
- global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModulesField),
- v8::Object::New(isolate));
global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem),
v8::External::New(isolate, this));
+
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context->v8_context());
+ DCHECK(registry);
+ registry->AddObserver(this);
+ registry->AddBuiltinModule(
+ GetIsolate(), "array", context->safe_builtins()->GetArray());
+ registry->AddBuiltinModule(GetIsolate(), "console", console::AsV8Object());
+ registry->AddBuiltinModule(
+ GetIsolate(), "function", context->safe_builtins()->GetFunction());
+ registry->AddBuiltinModule(
+ GetIsolate(), "json", context->safe_builtins()->GetJSON());
+ registry->AddBuiltinModule(
+ GetIsolate(), "object", context->safe_builtins()->GetObjekt());
+ registry->AddBuiltinModule(
+ GetIsolate(), "regexp", context->safe_builtins()->GetRegExp());
+ registry->AddBuiltinModule(
+ GetIsolate(), "string", context->safe_builtins()->GetString());
+ v8::Handle<v8::Object> natives(NewInstance());
+ registry->AddBuiltinModule(
+ GetIsolate(),
+ "require",
+ natives->Get(v8::String::NewFromUtf8(
+ GetIsolate(), "require", v8::String::kInternalizedString)));
+ registry->AddBuiltinModule(
+ GetIsolate(),
+ "requireNative",
+ natives->Get(v8::String::NewFromUtf8(
+ GetIsolate(), "requireNative", v8::String::kInternalizedString)));
+ registry->AddBuiltinModule(
+ GetIsolate(),
+ "privates",
+ natives->Get(v8::String::NewFromUtf8(
+ GetIsolate(), "privates", v8::String::kInternalizedString)));
+
+ modules_supporting_amd_.insert("app.runtime");
+ modules_supporting_amd_.insert("entryIdManager");
}
ModuleSystem::~ModuleSystem() { Invalidate(); }
@@ -151,8 +186,6 @@ void ModuleSystem::Invalidate() {
v8::HandleScope scope(GetIsolate());
v8::Handle<v8::Object> global = context()->v8_context()->Global();
global->DeleteHiddenValue(
- v8::String::NewFromUtf8(GetIsolate(), kModulesField));
- global->DeleteHiddenValue(
v8::String::NewFromUtf8(GetIsolate(), kModuleSystem));
}
@@ -198,74 +231,116 @@ v8::Local<v8::Value> ModuleSystem::RequireForJsInner(
v8::EscapableHandleScope handle_scope(GetIsolate());
v8::Context::Scope context_scope(context()->v8_context());
- v8::Handle<v8::Object> global(context()->v8_context()->Global());
+ std::string module_name_str =
+ std::string(*v8::String::Utf8Value(module_name));
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context()->v8_context());
+ if (!registry) {
+ return handle_scope.Escape(
+ v8::Local<v8::Primitive>(v8::Undefined(GetIsolate())));
+ }
- // The module system might have been deleted. This can happen if a different
- // context keeps a reference to us, but our frame is destroyed (e.g.
- // background page keeps reference to chrome object in a closed popup).
- v8::Handle<v8::Value> modules_value = global->GetHiddenValue(
- v8::String::NewFromUtf8(GetIsolate(), kModulesField));
- if (modules_value.IsEmpty() || modules_value->IsUndefined()) {
- Warn(GetIsolate(), "Extension view no longer exists");
- return v8::Undefined(GetIsolate());
+ if (registry->available_modules().count(module_name_str) == 0 &&
+ !LoadModule(module_name_str)) {
+ return handle_scope.Escape(
+ v8::Local<v8::Primitive>(v8::Undefined(GetIsolate())));
}
+ return handle_scope.Escape(
+ v8::Local<v8::Value>(registry->GetModule(GetIsolate(), module_name_str)));
+}
+
+bool ModuleSystem::LoadModule(const std::string& module_name) {
+ if (failed_module_loads_.count(module_name) != 0)
+ return false;
- v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(modules_value));
- v8::Local<v8::Value> exports(modules->Get(module_name));
- if (!exports->IsUndefined())
- return handle_scope.Escape(exports);
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context()->v8_context());
+ DCHECK_EQ(0u, registry->available_modules().count(module_name));
+ v8::HandleScope handle_scope(GetIsolate());
+ v8::Context::Scope context_scope(context()->v8_context());
- std::string module_name_str = *v8::String::Utf8Value(module_name);
- v8::Handle<v8::Value> source(GetSource(module_name_str));
+ if (LoadNative(module_name))
+ return true;
+
+ v8::Handle<v8::Value> source(GetSource(module_name));
if (source.IsEmpty() || source->IsUndefined()) {
- Fatal(context_, "No source for require(" + module_name_str + ")");
- return v8::Undefined(GetIsolate());
+ Fatal(context_, "No source for module " + module_name);
+ return false;
}
v8::Handle<v8::String> wrapped_source(
- WrapSource(v8::Handle<v8::String>::Cast(source)));
+ WrapSource(v8::Handle<v8::String>::Cast(source), module_name));
// Modules are wrapped in (function(){...}) so they always return functions.
- v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name);
+ v8::Handle<v8::String> module_name_js(
+ v8::String::NewFromUtf8(GetIsolate(), module_name.c_str()));
+ v8::Handle<v8::Value> func_as_value =
+ RunString(wrapped_source, module_name_js);
if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
- Fatal(context_, "Bad source for require(" + module_name_str + ")");
- return v8::Undefined(GetIsolate());
+ Fatal(context_, "Bad source for module " + module_name);
+ return false;
}
v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value);
- exports = v8::Object::New(GetIsolate());
- v8::Handle<v8::Object> natives(NewInstance());
- CHECK(!natives.IsEmpty()); // this can happen if v8 has issues
+ v8::Handle<v8::Object> define_object = v8::Object::New(GetIsolate());
+ gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object);
- // These must match the argument order in WrapSource.
+ // These must match the argument order in WrapAmdSource.
v8::Handle<v8::Value> args[] = {
- // CommonJS.
- natives->Get(v8::String::NewFromUtf8(
- GetIsolate(), "require", v8::String::kInternalizedString)),
- natives->Get(v8::String::NewFromUtf8(
- GetIsolate(), "requireNative", v8::String::kInternalizedString)),
- exports,
- // Libraries that we magically expose to every module.
- console::AsV8Object(),
- natives->Get(v8::String::NewFromUtf8(
- GetIsolate(), "privates", v8::String::kInternalizedString)),
- // Each safe builtin. Keep in order with the arguments in WrapSource.
- context_->safe_builtins()->GetArray(),
- context_->safe_builtins()->GetFunction(),
- context_->safe_builtins()->GetJSON(),
- context_->safe_builtins()->GetObjekt(),
- context_->safe_builtins()->GetRegExp(),
- context_->safe_builtins()->GetString(), };
+ define_object->Get(v8::String::NewFromUtf8(GetIsolate(), "define")),
+ };
{
v8::TryCatch try_catch;
try_catch.SetCaptureMessage(true);
context_->CallFunction(func, arraysize(args), args);
- if (try_catch.HasCaught()) {
+ if (try_catch.HasCaught())
HandleException(try_catch);
- return v8::Undefined(GetIsolate());
- }
}
- modules->Set(module_name, exports);
- return handle_scope.Escape(exports);
+ if (registry->available_modules().count(module_name) == 0) {
+ failed_module_loads_.insert(module_name);
+ return false;
+ }
+ return true;
+}
+
+bool ModuleSystem::LoadNative(const std::string& native_name) {
+ if (natives_enabled_ == 0)
+ return false;
+
+ v8::HandleScope scope(GetIsolate());
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context_->v8_context());
+ if (overridden_native_handlers_.count(native_name) > 0u)
+ return false;
+
+ NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
+ if (i == native_handler_map_.end()) {
+ return false;
+ }
+
+ registry->AddBuiltinModule(
+ GetIsolate(), native_name, i->second->NewInstance());
+ return true;
+}
+
+void ModuleSystem::OnDidAddPendingModule(
+ const std::string& id,
+ const std::vector<std::string>& dependencies) {
+ if (!source_map_->Contains(id))
+ return;
+
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context_->v8_context());
+ for (std::vector<std::string>::const_iterator it = dependencies.begin();
+ it != dependencies.end();
+ ++it) {
+ if (registry->available_modules().count(*it) != 0)
+ continue;
+
+ if (!LoadModule(*it))
+ LOG(DFATAL) << "Invalid dependency " << *it << " in module " << id;
+ }
+ gin::ModuleRegistry::From(context_->v8_context())
+ ->AttemptToLoadMoreModules(GetIsolate());
}
v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
@@ -543,30 +618,59 @@ v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString(
Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
return v8::Undefined(GetIsolate());
}
+ gin::ModuleRegistry* registry =
+ gin::ModuleRegistry::From(context()->v8_context());
+ if (!registry)
+ return v8::Undefined(GetIsolate());
- if (overridden_native_handlers_.count(native_name) > 0u) {
- return RequireForJsInner(
- v8::String::NewFromUtf8(GetIsolate(), native_name.c_str()));
- }
-
- NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
- if (i == native_handler_map_.end()) {
+ if (registry->available_modules().count(native_name) == 0 &&
+ !LoadModule(native_name)) {
Fatal(context_,
"Couldn't find native for requireNative(" + native_name + ")");
return v8::Undefined(GetIsolate());
}
- return i->second->NewInstance();
+ return registry->GetModule(GetIsolate(), native_name);
}
-v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) {
+v8::Handle<v8::String> ModuleSystem::WrapSource(
+ v8::Handle<v8::String> source,
+ const std::string& module_name) {
+ if (modules_supporting_amd_.count(module_name) != 0 ||
+ module_name.find('/') != std::string::npos) {
+ return WrapAmdSource(source);
+ }
+
v8::EscapableHandleScope handle_scope(GetIsolate());
- // Keep in order with the arguments in RequireForJsInner.
- v8::Handle<v8::String> left = v8::String::NewFromUtf8(
- GetIsolate(),
- "(function(require, requireNative, exports, "
- "console, privates,"
- "$Array, $Function, $JSON, $Object, $RegExp, $String) {"
- "'use strict';");
+ v8::Handle<v8::String> left =
+ v8::String::NewFromUtf8(GetIsolate(),
+ ("define('" + module_name +
+ "', ["
+ "'require',"
+ "'requireNative',"
+ "'privates',"
+ "'array',"
+ "'function',"
+ "'json',"
+ "'object',"
+ "'regexp',"
+ "'string',"
+ "'console',"
+ "], function(require, requireNative, privates, "
+ "$Array, $Function, $JSON, "
+ "$Object, $RegExp, $String, console) {"
+ "var exports = {};").c_str());
+ v8::Handle<v8::String> right =
+ v8::String::NewFromUtf8(GetIsolate(), "\nreturn exports;})");
+ return handle_scope.Escape(v8::Local<v8::String>(WrapAmdSource(
+ v8::String::Concat(left, v8::String::Concat(source, right)))));
+}
+
+v8::Handle<v8::String> ModuleSystem::WrapAmdSource(
+ v8::Handle<v8::String> source) {
+ v8::EscapableHandleScope handle_scope(GetIsolate());
+ // Keep in order with the arguments in LoadModule.
+ v8::Handle<v8::String> left =
+ v8::String::NewFromUtf8(GetIsolate(), "(function(define) {'use strict';");
v8::Handle<v8::String> right = v8::String::NewFromUtf8(GetIsolate(), "\n})");
return handle_scope.Escape(v8::Local<v8::String>(
v8::String::Concat(left, v8::String::Concat(source, right))));
« no previous file with comments | « extensions/renderer/module_system.h ('k') | extensions/renderer/resources/app_runtime_custom_bindings.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698