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

Side by Side Diff: gin/modules/module_registry.cc

Issue 62333018: Implement Asynchronous Module Definition API for Mojo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moar testing Created 7 years, 1 month 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
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gin/modules/module_registry.h"
6
7 #include <assert.h>
8 #include <string>
9 #include <vector>
10 #include "gin/arguments.h"
11 #include "gin/converter.h"
12 #include "gin/per_isolate_data.h"
13 #include "gin/wrapper_info.h"
14
15 using v8::Handle;
16 using v8::Isolate;
17 using v8::ObjectTemplate;
18
19 namespace gin {
20
21 struct PendingModule {
22 PendingModule();
23 ~PendingModule();
24
25 std::string id;
26 std::vector<std::string> dependencies;
27 v8::Persistent<v8::Value> factory;
28 };
29
30 namespace {
31
32 void Define(const v8::FunctionCallbackInfo<v8::Value>& info) {
33 Arguments args(info);
34
35 if (!info.Length())
36 return args.ThrowTypeError("At least one argument is required.");
37
38 std::string id;
39 std::vector<std::string> dependencies;
40 Handle<v8::Value> factory;
41
42 if (args.PeekNext()->IsString())
43 args.GetNext(&id);
44 if (args.PeekNext()->IsArray())
45 args.GetNext(&dependencies);
46 if (!args.GetNext(&factory))
Aaron Boodman 2013/11/15 18:56:06 "Factory" seems like a weird name for the function
abarth-chromium 2013/11/15 19:13:37 In AMD, you can either supply a function or an obj
47 return args.ThrowError();
48
49 PendingModule* pending = new PendingModule;
50 pending->id = id;
51 pending->dependencies = dependencies;
52 pending->factory.Reset(args.isolate(), factory);
53
54 ModuleRegistry* registry =
55 ModuleRegistry::From(args.isolate()->GetCurrentContext());
56 registry->AddPendingModule(args.isolate(), pending);
57 }
58
59 WrapperInfo g_wrapper_info = {};
60
61 v8::Local<v8::FunctionTemplate> GetDefineTemplate(v8::Isolate* isolate) {
62 PerIsolateData* data = PerIsolateData::From(isolate);
63 v8::Local<v8::FunctionTemplate> templ = data->GetFunctionTemplate(
64 &g_wrapper_info);
65 if (templ.IsEmpty()) {
66 templ = v8::FunctionTemplate::New(Define);
67 templ->SetLength(3);
Aaron Boodman 2013/11/15 18:56:06 I don't think this is really necessary, fwiw.
abarth-chromium 2013/11/15 19:13:37 Ok, I'll remove it. It's visible in JavaScript, b
68 data->SetFunctionTemplate(&g_wrapper_info, templ);
69 }
70 return templ;
71 }
72
73 } // namespace gin
74
75
76 PendingModule::PendingModule() {
77 }
78
79 PendingModule::~PendingModule() {
80 factory.Reset();
81 }
82
83 ModuleRegistry::ModuleRegistry(v8::Isolate* isolate)
84 : modules_(isolate, v8::Object::New()) {
85 }
86
87 ModuleRegistry::~ModuleRegistry() {
88 for (PendingModuleList::iterator it = pending_modules_.begin();
89 it != pending_modules_.end(); ++it) {
90 delete *it;
91 }
92 modules_.Reset();
93 }
94
95 void ModuleRegistry::RegisterGlobals(v8::Isolate* isolate,
96 Handle<v8::ObjectTemplate> templ) {
97 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
98 }
99
100 void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
101 const std::string& id,
102 Handle<ObjectTemplate> templ) {
103 assert(!id.empty());
104 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
105 modules->Set(StringToV8(isolate, id), templ->NewInstance());
106 }
107
108 ModuleRegistry* ModuleRegistry::From(Handle<v8::Context> context) {
109 v8::Isolate* isolate = context->GetIsolate();
110 Handle<v8::String> key = Key(isolate);
111 Handle<v8::Value> encoded = context->Global()->GetHiddenValue(key);
Aaron Boodman 2013/11/15 18:56:06 Why is this variable called "encoded"?
abarth-chromium 2013/11/15 19:13:37 Just because it's a pointer encoded into a v8 obje
112 if (encoded.IsEmpty() || !encoded->IsExternal()) {
113 PerContextData* data = PerContextData::From(context);
114 if (!data)
115 return NULL;
116 ModuleRegistry* registry = new ModuleRegistry(isolate);
117 context->Global()->SetHiddenValue(key, v8::External::New(registry));
118 data->AddSupplement(registry);
119 return registry;
120 }
121 Handle<v8::External> external = Handle<v8::External>::Cast(encoded);
122 return static_cast<ModuleRegistry*>(external->Value());
123 }
124
125 void ModuleRegistry::AddPendingModule(v8::Isolate* isolate,
126 PendingModule* pending) {
127 if (AttemptToLoad(isolate, pending))
128 AttemptToLoadPendingModules(isolate);
129 }
130
131 Handle<v8::String> ModuleRegistry::Key(v8::Isolate* isolate) {
Aaron Boodman 2013/11/15 18:56:06 ::GetHiddenValueKey(). Also, this could just be a
abarth-chromium 2013/11/15 19:13:37 Will do.
132 return StringToSymbol(isolate, "::gin::ModuleRegistry");
133 }
134
135 void ModuleRegistry::Detach(Handle<v8::Context> context) {
136 context->Global()->SetHiddenValue(Key(context->GetIsolate()),
137 Handle<v8::Value>());
138 }
139
140 bool ModuleRegistry::AttemptToLoad(v8::Isolate* isolate,
141 PendingModule* pending) {
142 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
143 Handle<v8::String> key = StringToV8(isolate, pending->id);
144
145 if (!pending->id.empty() && modules->HasOwnProperty(key)) {
146 // We've already loaded a module with this name. Ignore the new one.
147 delete pending;
148 return true;
149 }
150
151 size_t argc = pending->dependencies.size();
152 std::vector<Handle<v8::Value> > argv(argc);
153 for (size_t i = 0; i < argc; ++i) {
154 Handle<v8::String> key = StringToV8(isolate, pending->dependencies[i]);
155 if (!modules->HasOwnProperty(key)) {
156 pending_modules_.push_back(pending);
157 return false;
158 }
159 argv[i] = modules->Get(key);
160 }
161
162 Handle<v8::Value> module = v8::Local<v8::Value>::New(
163 isolate, pending->factory);
164
165 Handle<v8::Function> factory;
166 if (ConvertFromV8(module, &factory)) {
167 v8::Handle<v8::Object> global = isolate->GetCurrentContext()->Global();
168 module = factory->Call(global, argc, argv.data());
169 // TODO(abarth): What should we do with exceptions?
170 }
171
172 if (!pending->id.empty() && !module.IsEmpty())
173 modules->Set(key, module);
174
175 delete pending;
176 return true;
177 }
178
179 void ModuleRegistry::AttemptToLoadPendingModules(v8::Isolate* isolate) {
180 PendingModuleList pending_modules;
181 pending_modules.swap(pending_modules_);
182 for (PendingModuleList::iterator it = pending_modules.begin();
183 it != pending_modules.end(); ++it) {
184 AttemptToLoad(isolate, *it);
185 }
186 }
187
188 } // namespace gin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698