blob: e84f0e072a133a9ef7b3d080470731ee8f1ad8a7 [file] [log] [blame]
[email protected]f55c90ee62014-04-12 00:50:031// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]58e10452012-02-22 03:34:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f55c90ee62014-04-12 00:50:035#include "extensions/renderer/module_system.h"
[email protected]58e10452012-02-22 03:34:456
7#include "base/bind.h"
[email protected]ad6aa8f92013-06-22 15:34:168#include "base/command_line.h"
kalmanb0c1c502015-04-15 00:25:069#include "base/logging.h"
[email protected]a714e462013-01-26 06:33:1010#include "base/stl_util.h"
[email protected]a19a16d82013-06-11 17:45:1211#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
primiano7182d7b2015-01-30 18:02:0313#include "base/trace_event/trace_event.h"
sammcfb8875c2014-10-28 11:51:0414#include "content/public/renderer/render_frame.h"
[email protected]4f1633f2013-03-09 14:26:2415#include "content/public/renderer/render_view.h"
thestigb012bc3d2014-09-18 22:57:1316#include "extensions/common/extension.h"
[email protected]f55c90ee62014-04-12 00:50:0317#include "extensions/common/extensions_client.h"
18#include "extensions/renderer/console.h"
19#include "extensions/renderer/safe_builtins.h"
20#include "extensions/renderer/script_context.h"
rdevlin.croninb2cec912015-06-24 20:36:0121#include "extensions/renderer/script_context_set.h"
bashi6a4854f2015-06-19 00:51:5122#include "extensions/renderer/v8_helpers.h"
[email protected]d9f51dad2014-07-09 05:39:3823#include "gin/modules/module_registry.h"
[email protected]2255a9332013-06-17 05:12:3124#include "third_party/WebKit/public/web/WebFrame.h"
25#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
[email protected]58e10452012-02-22 03:34:4526
[email protected]95ee77da2013-03-19 21:11:1127namespace extensions {
28
bashi6a4854f2015-06-19 00:51:5129using namespace v8_helpers;
30
[email protected]58e10452012-02-22 03:34:4531namespace {
32
[email protected]561ddce2012-03-22 01:18:5533const char* kModuleSystem = "module_system";
34const char* kModuleName = "module_name";
35const char* kModuleField = "module_field";
[email protected]bad9a5f2012-04-13 19:16:5436const char* kModulesField = "modules";
[email protected]cc0457712012-03-21 03:56:3837
kalmanec0e3aa2015-04-28 21:50:3238// Logs an error for the calling context in preparation for potentially
39// crashing the renderer, with some added metadata about the context:
[email protected]662c48b2013-07-12 03:50:5240// - Its type (blessed, unblessed, etc).
41// - Whether it's valid.
42// - The extension ID, if one exists.
kalmanec0e3aa2015-04-28 21:50:3243// Crashing won't happen in stable/beta releases, but is encouraged to happen
44// in the less stable released to catch errors early.
[email protected]f55c90ee62014-04-12 00:50:0345void Fatal(ScriptContext* context, const std::string& message) {
[email protected]662c48b2013-07-12 03:50:5246 // Prepend some context metadata.
47 std::string full_message = "(";
48 if (!context->is_valid())
49 full_message += "Invalid ";
50 full_message += context->GetContextTypeDescription();
51 full_message += " context";
52 if (context->extension()) {
53 full_message += " for ";
54 full_message += context->extension()->id();
55 }
56 full_message += ") ";
57 full_message += message;
58
kalman309f98b2015-04-30 00:12:0059 ExtensionsClient* client = ExtensionsClient::Get();
60 if (client->ShouldSuppressFatalErrors()) {
rdevlin.croninb2cec912015-06-24 20:36:0161 console::Error(context->GetRenderFrame(), full_message);
kalman309f98b2015-04-30 00:12:0062 client->RecordDidSuppressFatalError();
63 } else {
rdevlin.croninb2cec912015-06-24 20:36:0164 console::Fatal(context->GetRenderFrame(), full_message);
kalman309f98b2015-04-30 00:12:0065 }
[email protected]ad6aa8f92013-06-22 15:34:1666}
67
[email protected]95c6b3012013-12-02 14:30:3168void Warn(v8::Isolate* isolate, const std::string& message) {
rdevlin.croninb2cec912015-06-24 20:36:0169 ScriptContext* script_context =
jochen520e6222015-10-29 16:21:2470 ScriptContextSet::GetContextByV8Context(isolate->GetCurrentContext());
rdevlin.croninb2cec912015-06-24 20:36:0171 console::Warn(script_context ? script_context->GetRenderFrame() : nullptr,
72 message);
[email protected]ad6aa8f92013-06-22 15:34:1673}
74
[email protected]68e63ea12013-06-05 05:00:5475// Default exception handler which logs the exception.
76class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler {
77 public:
[email protected]f55c90ee62014-04-12 00:50:0378 explicit DefaultExceptionHandler(ScriptContext* context)
bashi6a4854f2015-06-19 00:51:5179 : ModuleSystem::ExceptionHandler(context) {}
[email protected]ad6aa8f92013-06-22 15:34:1680
[email protected]68e63ea12013-06-05 05:00:5481 // Fatally dumps the debug info from |try_catch| to the console.
82 // Make sure this is never used for exceptions that originate in external
83 // code!
dcheng9168b2f2014-10-21 12:38:2484 void HandleUncaughtException(const v8::TryCatch& try_catch) override {
[email protected]dc3d06e2013-09-06 12:21:0385 v8::HandleScope handle_scope(context_->isolate());
[email protected]68e63ea12013-06-05 05:00:5486 std::string stack_trace = "<stack trace unavailable>";
bashi6a4854f2015-06-19 00:51:5187 v8::Local<v8::Value> v8_stack_trace;
88 if (try_catch.StackTrace(context_->v8_context()).ToLocal(&v8_stack_trace)) {
89 v8::String::Utf8Value stack_value(v8_stack_trace);
[email protected]68e63ea12013-06-05 05:00:5490 if (*stack_value)
91 stack_trace.assign(*stack_value, stack_value.length());
92 else
93 stack_trace = "<could not convert stack trace to string>";
94 }
[email protected]662c48b2013-07-12 03:50:5295 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}");
[email protected]68e63ea12013-06-05 05:00:5496 }
97};
98
rdevlin.cronin83a4b3a2015-10-28 21:43:5899// Sets a property on the "exports" object for bindings. Called by JS with
100// exports.$set(<key>, <value>).
101void SetExportsProperty(
102 const v8::FunctionCallbackInfo<v8::Value>& args) {
103 v8::Local<v8::Object> obj = args.This();
rdevlin.cronin415b73b2015-11-13 01:14:47104 CHECK_EQ(2, args.Length());
105 CHECK(args[0]->IsString());
rdevlin.cronin83a4b3a2015-10-28 21:43:58106 v8::Maybe<bool> result =
107 obj->DefineOwnProperty(args.GetIsolate()->GetCurrentContext(),
108 args[0]->ToString(), args[1], v8::ReadOnly);
109 if (!result.FromMaybe(false))
110 LOG(ERROR) << "Failed to set private property on the export.";
111}
112
[email protected]f55c90ee62014-04-12 00:50:03113} // namespace
[email protected]68e63ea12013-06-05 05:00:54114
115std::string ModuleSystem::ExceptionHandler::CreateExceptionString(
116 const v8::TryCatch& try_catch) {
tfarinaf85316f2015-04-29 17:03:40117 v8::Local<v8::Message> message(try_catch.Message());
[email protected]95ee77da2013-03-19 21:11:11118 if (message.IsEmpty()) {
119 return "try_catch has no message";
120 }
[email protected]58e10452012-02-22 03:34:45121
[email protected]95ee77da2013-03-19 21:11:11122 std::string resource_name = "<unknown resource>";
[email protected]bce20ba2014-06-27 18:18:45123 if (!message->GetScriptOrigin().ResourceName().IsEmpty()) {
[email protected]95ee77da2013-03-19 21:11:11124 v8::String::Utf8Value resource_name_v8(
dcarneya261b772014-11-20 17:55:07125 message->GetScriptOrigin().ResourceName());
[email protected]95ee77da2013-03-19 21:11:11126 resource_name.assign(*resource_name_v8, resource_name_v8.length());
127 }
128
129 std::string error_message = "<no error message>";
130 if (!message->Get().IsEmpty()) {
131 v8::String::Utf8Value error_message_v8(message->Get());
132 error_message.assign(*error_message_v8, error_message_v8.length());
133 }
134
bashi6a4854f2015-06-19 00:51:51135 auto maybe = message->GetLineNumber(context_->v8_context());
136 int line_number = maybe.IsJust() ? maybe.FromJust() : 0;
[email protected]95ee77da2013-03-19 21:11:11137 return base::StringPrintf("%s:%d: %s",
138 resource_name.c_str(),
bashi6a4854f2015-06-19 00:51:51139 line_number,
[email protected]95ee77da2013-03-19 21:11:11140 error_message.c_str());
141}
142
[email protected]f55c90ee62014-04-12 00:50:03143ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map)
[email protected]4f1633f2013-03-09 14:26:24144 : ObjectBackedNativeHandler(context),
[email protected]68e63ea12013-06-05 05:00:54145 context_(context),
[email protected]bad9a5f2012-04-13 19:16:54146 source_map_(source_map),
[email protected]68e63ea12013-06-05 05:00:54147 natives_enabled_(0),
[email protected]d9f51dad2014-07-09 05:39:38148 exception_handler_(new DefaultExceptionHandler(context)),
149 weak_factory_(this) {
[email protected]f55c90ee62014-04-12 00:50:03150 RouteFunction(
151 "require",
[email protected]ecde1912012-03-16 06:25:31152 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this)));
[email protected]f55c90ee62014-04-12 00:50:03153 RouteFunction(
154 "requireNative",
[email protected]4f1633f2013-03-09 14:26:24155 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this)));
[email protected]d9f51dad2014-07-09 05:39:38156 RouteFunction(
157 "requireAsync",
158 base::Bind(&ModuleSystem::RequireAsync, base::Unretained(this)));
[email protected]ca557292013-12-11 08:44:27159 RouteFunction("privates",
[email protected]f55c90ee62014-04-12 00:50:03160 base::Bind(&ModuleSystem::Private, base::Unretained(this)));
[email protected]ecde1912012-03-16 06:25:31161
tfarinaf85316f2015-04-29 17:03:40162 v8::Local<v8::Object> global(context->v8_context()->Global());
[email protected]505ffde2013-12-19 15:47:13163 v8::Isolate* isolate = context->isolate();
jochen300abe232015-11-06 21:17:53164 SetPrivate(global, kModulesField, v8::Object::New(isolate));
165 SetPrivate(global, kModuleSystem, v8::External::New(isolate, this));
[email protected]d9f51dad2014-07-09 05:39:38166
167 gin::ModuleRegistry::From(context->v8_context())->AddObserver(this);
sammcfb8875c2014-10-28 11:51:04168 if (context_->GetRenderFrame()) {
169 context_->GetRenderFrame()->EnsureMojoBuiltinsAreAvailable(
170 context->isolate(), context->v8_context());
171 }
[email protected]58e10452012-02-22 03:34:45172}
173
kalmanb0c1c502015-04-15 00:25:06174ModuleSystem::~ModuleSystem() {
175}
[email protected]4f1633f2013-03-09 14:26:24176
177void ModuleSystem::Invalidate() {
[email protected]079532242013-03-12 06:01:10178 // Clear the module system properties from the global context. It's polite,
179 // and we use this as a signal in lazy handlers that we no longer exist.
180 {
[email protected]dc3d06e2013-09-06 12:21:03181 v8::HandleScope scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40182 v8::Local<v8::Object> global = context()->v8_context()->Global();
jochen300abe232015-11-06 21:17:53183 DeletePrivate(global, kModulesField);
184 DeletePrivate(global, kModuleSystem);
[email protected]079532242013-03-12 06:01:10185 }
186
kalmanb0c1c502015-04-15 00:25:06187 // Invalidate all active and clobbered NativeHandlers we own.
188 for (const auto& handler : native_handler_map_)
189 handler.second->Invalidate();
190 for (const auto& clobbered_handler : clobbered_native_handlers_)
191 clobbered_handler->Invalidate();
[email protected]079532242013-03-12 06:01:10192
[email protected]4f1633f2013-03-09 14:26:24193 ObjectBackedNativeHandler::Invalidate();
[email protected]58e10452012-02-22 03:34:45194}
195
[email protected]b6aad81c2012-03-27 08:45:15196ModuleSystem::NativesEnabledScope::NativesEnabledScope(
197 ModuleSystem* module_system)
198 : module_system_(module_system) {
199 module_system_->natives_enabled_++;
200}
201
202ModuleSystem::NativesEnabledScope::~NativesEnabledScope() {
203 module_system_->natives_enabled_--;
204 CHECK_GE(module_system_->natives_enabled_, 0);
205}
206
[email protected]144114942012-12-04 07:23:23207void ModuleSystem::HandleException(const v8::TryCatch& try_catch) {
[email protected]68e63ea12013-06-05 05:00:54208 exception_handler_->HandleUncaughtException(try_catch);
[email protected]1c6189f2012-05-18 06:45:52209}
210
bashi61ca3c72015-06-26 00:40:10211v8::MaybeLocal<v8::Object> ModuleSystem::Require(
212 const std::string& module_name) {
213 v8::Local<v8::String> v8_module_name;
214 if (!ToV8String(GetIsolate(), module_name, &v8_module_name))
215 return v8::MaybeLocal<v8::Object>();
[email protected]95c6b3012013-12-02 14:30:31216 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi61ca3c72015-06-26 00:40:10217 v8::Local<v8::Value> value = RequireForJsInner(
218 v8_module_name);
219 if (value.IsEmpty() || !value->IsObject())
220 return v8::MaybeLocal<v8::Object>();
221 return handle_scope.Escape(value.As<v8::Object>());
[email protected]ecde1912012-03-16 06:25:31222}
223
[email protected]d8c5fbb2013-06-14 11:35:25224void ModuleSystem::RequireForJs(
[email protected]f55c90ee62014-04-12 00:50:03225 const v8::FunctionCallbackInfo<v8::Value>& args) {
bashi6a4854f2015-06-19 00:51:51226 if (!args[0]->IsString()) {
227 NOTREACHED() << "require() called with a non-string argument";
228 return;
229 }
230 v8::Local<v8::String> module_name = args[0].As<v8::String>();
[email protected]d8c5fbb2013-06-14 11:35:25231 args.GetReturnValue().Set(RequireForJsInner(module_name));
[email protected]ecde1912012-03-16 06:25:31232}
233
[email protected]95c6b3012013-12-02 14:30:31234v8::Local<v8::Value> ModuleSystem::RequireForJsInner(
tfarinaf85316f2015-04-29 17:03:40235 v8::Local<v8::String> module_name) {
[email protected]95c6b3012013-12-02 14:30:31236 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51237 v8::Local<v8::Context> v8_context = context()->v8_context();
238 v8::Context::Scope context_scope(v8_context);
[email protected]95ee77da2013-03-19 21:11:11239
tfarinaf85316f2015-04-29 17:03:40240 v8::Local<v8::Object> global(context()->v8_context()->Global());
[email protected]079532242013-03-12 06:01:10241
242 // The module system might have been deleted. This can happen if a different
243 // context keeps a reference to us, but our frame is destroyed (e.g.
244 // background page keeps reference to chrome object in a closed popup).
jochen300abe232015-11-06 21:17:53245 v8::Local<v8::Value> modules_value;
246 if (!GetPrivate(global, kModulesField, &modules_value) ||
247 modules_value->IsUndefined()) {
[email protected]95c6b3012013-12-02 14:30:31248 Warn(GetIsolate(), "Extension view no longer exists");
249 return v8::Undefined(GetIsolate());
[email protected]d2663612013-03-17 09:25:56250 }
[email protected]079532242013-03-12 06:01:10251
tfarinaf85316f2015-04-29 17:03:40252 v8::Local<v8::Object> modules(v8::Local<v8::Object>::Cast(modules_value));
bashi6a4854f2015-06-19 00:51:51253 v8::Local<v8::Value> exports;
254 if (!GetProperty(v8_context, modules, module_name, &exports) ||
255 !exports->IsUndefined())
[email protected]95c6b3012013-12-02 14:30:31256 return handle_scope.Escape(exports);
[email protected]7c95c1a82012-04-17 02:11:33257
[email protected]d9f51dad2014-07-09 05:39:38258 exports = LoadModule(*v8::String::Utf8Value(module_name));
bashi6a4854f2015-06-19 00:51:51259 SetProperty(v8_context, modules, module_name, exports);
[email protected]95c6b3012013-12-02 14:30:31260 return handle_scope.Escape(exports);
[email protected]58e10452012-02-22 03:34:45261}
262
[email protected]4f1633f2013-03-09 14:26:24263v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
264 const std::string& module_name,
265 const std::string& method_name) {
[email protected]f80685c32014-07-26 19:48:04266 v8::EscapableHandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40267 v8::Local<v8::Value> no_args;
[email protected]f80685c32014-07-26 19:48:04268 return handle_scope.Escape(
269 CallModuleMethod(module_name, method_name, 0, &no_args));
[email protected]a714e462013-01-26 06:33:10270}
271
272v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
273 const std::string& module_name,
274 const std::string& method_name,
tfarinaf85316f2015-04-29 17:03:40275 std::vector<v8::Local<v8::Value>>* args) {
[email protected]68e63ea12013-06-05 05:00:54276 return CallModuleMethod(
277 module_name, method_name, args->size(), vector_as_array(args));
278}
279
280v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
281 const std::string& module_name,
282 const std::string& method_name,
283 int argc,
tfarinaf85316f2015-04-29 17:03:40284 v8::Local<v8::Value> argv[]) {
[email protected]f55c90ee62014-04-12 00:50:03285 TRACE_EVENT2("v8",
286 "v8.callModuleMethod",
287 "module_name",
288 module_name,
289 "method_name",
290 method_name);
[email protected]68e63ea12013-06-05 05:00:54291
[email protected]95c6b3012013-12-02 14:30:31292 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51293 v8::Local<v8::Context> v8_context = context()->v8_context();
294 v8::Context::Scope context_scope(v8_context);
295
296 v8::Local<v8::String> v8_module_name;
297 v8::Local<v8::String> v8_method_name;
298 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) ||
299 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) {
300 return handle_scope.Escape(v8::Undefined(GetIsolate()));
301 }
[email protected]68e63ea12013-06-05 05:00:54302
303 v8::Local<v8::Value> module;
304 {
305 NativesEnabledScope natives_enabled(this);
bashi6a4854f2015-06-19 00:51:51306 module = RequireForJsInner(v8_module_name);
[email protected]68e63ea12013-06-05 05:00:54307 }
308
[email protected]95ee77da2013-03-19 21:11:11309 if (module.IsEmpty() || !module->IsObject()) {
[email protected]662c48b2013-07-12 03:50:52310 Fatal(context_,
[email protected]ad6aa8f92013-06-22 15:34:16311 "Failed to get module " + module_name + " to call " + method_name);
bashi6a4854f2015-06-19 00:51:51312 return handle_scope.Escape(v8::Undefined(GetIsolate()));
[email protected]95ee77da2013-03-19 21:11:11313 }
314
bashi6a4854f2015-06-19 00:51:51315 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module);
316 v8::Local<v8::Value> value;
317 if (!GetProperty(v8_context, object, v8_method_name, &value) ||
318 !value->IsFunction()) {
[email protected]662c48b2013-07-12 03:50:52319 Fatal(context_, module_name + "." + method_name + " is not a function");
bashi6a4854f2015-06-19 00:51:51320 return handle_scope.Escape(v8::Undefined(GetIsolate()));
[email protected]95ee77da2013-03-19 21:11:11321 }
322
tfarinaf85316f2015-04-29 17:03:40323 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(value);
[email protected]a714e462013-01-26 06:33:10324 v8::Local<v8::Value> result;
[email protected]2bcbf712012-09-05 06:58:49325 {
bashi6a4854f2015-06-19 00:51:51326 v8::TryCatch try_catch(GetIsolate());
[email protected]2bcbf712012-09-05 06:58:49327 try_catch.SetCaptureMessage(true);
[email protected]68e63ea12013-06-05 05:00:54328 result = context_->CallFunction(func, argc, argv);
bashi6a4854f2015-06-19 00:51:51329 if (try_catch.HasCaught()) {
[email protected]144114942012-12-04 07:23:23330 HandleException(try_catch);
bashi6a4854f2015-06-19 00:51:51331 result = v8::Undefined(GetIsolate());
332 }
[email protected]2bcbf712012-09-05 06:58:49333 }
[email protected]95c6b3012013-12-02 14:30:31334 return handle_scope.Escape(result);
[email protected]2bcbf712012-09-05 06:58:49335}
336
[email protected]f55c90ee62014-04-12 00:50:03337void ModuleSystem::RegisterNativeHandler(
338 const std::string& name,
[email protected]58e10452012-02-22 03:34:45339 scoped_ptr<NativeHandler> native_handler) {
kalmanb0c1c502015-04-15 00:25:06340 ClobberExistingNativeHandler(name);
[email protected]58e10452012-02-22 03:34:45341 native_handler_map_[name] =
342 linked_ptr<NativeHandler>(native_handler.release());
343}
344
[email protected]95ee77da2013-03-19 21:11:11345void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) {
kalmanb0c1c502015-04-15 00:25:06346 ClobberExistingNativeHandler(name);
[email protected]11844fa2012-05-10 00:35:59347 overridden_native_handlers_.insert(name);
348}
349
[email protected]ecde1912012-03-16 06:25:31350void ModuleSystem::RunString(const std::string& code, const std::string& name) {
[email protected]dc3d06e2013-09-06 12:21:03351 v8::HandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51352 v8::Local<v8::String> v8_code;
353 v8::Local<v8::String> v8_name;
354 if (!ToV8String(GetIsolate(), code.c_str(), &v8_code) ||
355 !ToV8String(GetIsolate(), name.c_str(), &v8_name)) {
356 Warn(GetIsolate(), "Too long code or name.");
357 return;
358 }
359 RunString(v8_code, v8_name);
[email protected]58e10452012-02-22 03:34:45360}
361
[email protected]cc0457712012-03-21 03:56:38362// static
[email protected]4e008e172013-06-13 20:15:48363void ModuleSystem::NativeLazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51364 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48365 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51366 LazyFieldGetterInner(property.As<v8::String>(), info,
367 &ModuleSystem::RequireNativeFromString);
[email protected]4e008e172013-06-13 20:15:48368}
369
370// static
371void ModuleSystem::LazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51372 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48373 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51374 LazyFieldGetterInner(property.As<v8::String>(), info, &ModuleSystem::Require);
[email protected]4e008e172013-06-13 20:15:48375}
376
377// static
378void ModuleSystem::LazyFieldGetterInner(
379 v8::Local<v8::String> property,
380 const v8::PropertyCallbackInfo<v8::Value>& info,
[email protected]4f1633f2013-03-09 14:26:24381 RequireFunction require_function) {
[email protected]561ddce2012-03-22 01:18:55382 CHECK(!info.Data().IsEmpty());
383 CHECK(info.Data()->IsObject());
jochen300abe232015-11-06 21:17:53384 v8::Isolate* isolate = info.GetIsolate();
385 v8::HandleScope handle_scope(isolate);
tfarinaf85316f2015-04-29 17:03:40386 v8::Local<v8::Object> parameters = v8::Local<v8::Object>::Cast(info.Data());
[email protected]9a598442013-06-04 16:39:12387 // This context should be the same as context()->v8_context().
tfarinaf85316f2015-04-29 17:03:40388 v8::Local<v8::Context> context = parameters->CreationContext();
389 v8::Local<v8::Object> global(context->Global());
jochen300abe232015-11-06 21:17:53390 v8::Local<v8::Value> module_system_value;
391 if (!GetPrivate(context, global, kModuleSystem, &module_system_value) ||
392 !module_system_value->IsExternal()) {
[email protected]bad9a5f2012-04-13 19:16:54393 // ModuleSystem has been deleted.
[email protected]95ee77da2013-03-19 21:11:11394 // TODO(kalman): See comment in header file.
jochen300abe232015-11-06 21:17:53395 Warn(isolate,
[email protected]95c6b3012013-12-02 14:30:31396 "Module system has been deleted, does extension view exist?");
[email protected]4e008e172013-06-13 20:15:48397 return;
[email protected]bad9a5f2012-04-13 19:16:54398 }
[email protected]95ee77da2013-03-19 21:11:11399
[email protected]561ddce2012-03-22 01:18:55400 ModuleSystem* module_system = static_cast<ModuleSystem*>(
tfarinaf85316f2015-04-29 17:03:40401 v8::Local<v8::External>::Cast(module_system_value)->Value());
[email protected]cc0457712012-03-21 03:56:38402
bashi6a4854f2015-06-19 00:51:51403 v8::Local<v8::Value> v8_module_name;
404 if (!GetProperty(context, parameters, kModuleName, &v8_module_name)) {
jochen300abe232015-11-06 21:17:53405 Warn(isolate, "Cannot find module.");
bashi6a4854f2015-06-19 00:51:51406 return;
407 }
408 std::string name = *v8::String::Utf8Value(v8_module_name);
[email protected]4f1633f2013-03-09 14:26:24409
410 // Switch to our v8 context because we need functions created while running
411 // the require()d module to belong to our context, not the current one.
412 v8::Context::Scope context_scope(context);
413 NativesEnabledScope natives_enabled_scope(module_system);
414
jochen300abe232015-11-06 21:17:53415 v8::TryCatch try_catch(isolate);
bashi61ca3c72015-06-26 00:40:10416 v8::Local<v8::Value> module_value;
417 if (!(module_system->*require_function)(name).ToLocal(&module_value)) {
[email protected]4f1633f2013-03-09 14:26:24418 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48419 return;
[email protected]95ee77da2013-03-19 21:11:11420 }
[email protected]4f1633f2013-03-09 14:26:24421
tfarinaf85316f2015-04-29 17:03:40422 v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(module_value);
bashi6a4854f2015-06-19 00:51:51423 v8::Local<v8::Value> field_value;
424 if (!GetProperty(context, parameters, kModuleField, &field_value)) {
425 module_system->HandleException(try_catch);
426 return;
427 }
428 v8::Local<v8::String> field;
429 if (!field_value->ToString(context).ToLocal(&field)) {
430 module_system->HandleException(try_catch);
431 return;
432 }
[email protected]561ddce2012-03-22 01:18:55433
bashi6a4854f2015-06-19 00:51:51434 if (!IsTrue(module->Has(context, field))) {
[email protected]d7cd1b02013-09-10 00:22:16435 std::string field_str = *v8::String::Utf8Value(field);
[email protected]662c48b2013-07-12 03:50:52436 Fatal(module_system->context_,
437 "Lazy require of " + name + "." + field_str + " did not set the " +
438 field_str + " field");
[email protected]4e008e172013-06-13 20:15:48439 return;
[email protected]95ee77da2013-03-19 21:11:11440 }
[email protected]4f1633f2013-03-09 14:26:24441
bashi6a4854f2015-06-19 00:51:51442 v8::Local<v8::Value> new_field;
443 if (!GetProperty(context, module, field, &new_field)) {
[email protected]95ee77da2013-03-19 21:11:11444 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48445 return;
[email protected]95ee77da2013-03-19 21:11:11446 }
447
448 // Ok for it to be undefined, among other things it's how bindings signify
449 // that the extension doesn't have permission to use them.
450 CHECK(!new_field.IsEmpty());
451
[email protected]4f1633f2013-03-09 14:26:24452 // Delete the getter and set this field to |new_field| so the same object is
453 // returned every time a certain API is accessed.
tfarinaf85316f2015-04-29 17:03:40454 v8::Local<v8::Value> val = info.This();
[email protected]80b0c8c2014-04-22 15:00:43455 if (val->IsObject()) {
tfarinaf85316f2015-04-29 17:03:40456 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(val);
bashi6a4854f2015-06-19 00:51:51457 object->Delete(context, property);
458 SetProperty(context, object, property, new_field);
[email protected]80b0c8c2014-04-22 15:00:43459 } else {
460 NOTREACHED();
461 }
[email protected]4e008e172013-06-13 20:15:48462 info.GetReturnValue().Set(new_field);
[email protected]561ddce2012-03-22 01:18:55463}
464
tfarinaf85316f2015-04-29 17:03:40465void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]561ddce2012-03-22 01:18:55466 const std::string& field,
467 const std::string& module_name,
468 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03469 SetLazyField(
470 object, field, module_name, module_field, &ModuleSystem::LazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24471}
472
tfarinaf85316f2015-04-29 17:03:40473void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24474 const std::string& field,
475 const std::string& module_name,
476 const std::string& module_field,
bashi6a4854f2015-06-19 00:51:51477 v8::AccessorNameGetterCallback getter) {
478 CHECK(field.size() < v8::String::kMaxLength);
479 CHECK(module_name.size() < v8::String::kMaxLength);
480 CHECK(module_field.size() < v8::String::kMaxLength);
[email protected]dc3d06e2013-09-06 12:21:03481 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40482 v8::Local<v8::Object> parameters = v8::Object::New(GetIsolate());
bashi6a4854f2015-06-19 00:51:51483 v8::Local<v8::Context> context = context_->v8_context();
484 SetProperty(context, parameters, kModuleName,
485 ToV8StringUnsafe(GetIsolate(), module_name.c_str()));
486 SetProperty(context, parameters, kModuleField,
487 ToV8StringUnsafe(GetIsolate(), module_field.c_str()));
488 auto maybe = object->SetAccessor(
489 context, ToV8StringUnsafe(GetIsolate(), field.c_str()), getter, NULL,
490 parameters);
491 CHECK(IsTrue(maybe));
[email protected]cc0457712012-03-21 03:56:38492}
[email protected]ecde1912012-03-16 06:25:31493
tfarinaf85316f2015-04-29 17:03:40494void ModuleSystem::SetNativeLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24495 const std::string& field,
496 const std::string& module_name,
497 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03498 SetLazyField(object,
499 field,
500 module_name,
501 module_field,
502 &ModuleSystem::NativeLazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24503}
504
tfarinaf85316f2015-04-29 17:03:40505v8::Local<v8::Value> ModuleSystem::RunString(v8::Local<v8::String> code,
506 v8::Local<v8::String> name) {
annekao533482222015-08-21 23:23:53507 return context_->RunScript(
508 name, code, base::Bind(&ExceptionHandler::HandleUncaughtException,
509 base::Unretained(exception_handler_.get())));
[email protected]9e03ce22012-03-13 08:50:05510}
511
tfarinaf85316f2015-04-29 17:03:40512v8::Local<v8::Value> ModuleSystem::GetSource(const std::string& module_name) {
[email protected]95c6b3012013-12-02 14:30:31513 v8::EscapableHandleScope handle_scope(GetIsolate());
[email protected]ecde1912012-03-16 06:25:31514 if (!source_map_->Contains(module_name))
[email protected]95c6b3012013-12-02 14:30:31515 return v8::Undefined(GetIsolate());
516 return handle_scope.Escape(
517 v8::Local<v8::Value>(source_map_->GetSource(GetIsolate(), module_name)));
[email protected]58e10452012-02-22 03:34:45518}
519
[email protected]d8c5fbb2013-06-14 11:35:25520void ModuleSystem::RequireNative(
521 const v8::FunctionCallbackInfo<v8::Value>& args) {
[email protected]58e10452012-02-22 03:34:45522 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07523 std::string native_name = *v8::String::Utf8Value(args[0]);
bashi61ca3c72015-06-26 00:40:10524 v8::Local<v8::Object> object;
525 if (RequireNativeFromString(native_name).ToLocal(&object))
526 args.GetReturnValue().Set(object);
[email protected]4f1633f2013-03-09 14:26:24527}
528
bashi61ca3c72015-06-26 00:40:10529v8::MaybeLocal<v8::Object> ModuleSystem::RequireNativeFromString(
[email protected]4f1633f2013-03-09 14:26:24530 const std::string& native_name) {
[email protected]95ee77da2013-03-19 21:11:11531 if (natives_enabled_ == 0) {
532 // HACK: if in test throw exception so that we can test the natives-disabled
533 // logic; however, under normal circumstances, this is programmer error so
534 // we could crash.
[email protected]9c47471e2013-11-28 14:41:21535 if (exception_handler_) {
bashi61ca3c72015-06-26 00:40:10536 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51537 ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
bashi61ca3c72015-06-26 00:40:10538 return v8::MaybeLocal<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21539 }
[email protected]662c48b2013-07-12 03:50:52540 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10541 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11542 }
543
[email protected]9c47471e2013-11-28 14:41:21544 if (overridden_native_handlers_.count(native_name) > 0u) {
bashi61ca3c72015-06-26 00:40:10545 v8::Local<v8::Value> value = RequireForJsInner(
bashi6a4854f2015-06-19 00:51:51546 ToV8StringUnsafe(GetIsolate(), native_name.c_str()));
bashi61ca3c72015-06-26 00:40:10547 if (value.IsEmpty() || !value->IsObject())
548 return v8::MaybeLocal<v8::Object>();
549 return value.As<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21550 }
[email protected]95ee77da2013-03-19 21:11:11551
[email protected]58e10452012-02-22 03:34:45552 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
[email protected]95ee77da2013-03-19 21:11:11553 if (i == native_handler_map_.end()) {
[email protected]662c48b2013-07-12 03:50:52554 Fatal(context_,
[email protected]ad6aa8f92013-06-22 15:34:16555 "Couldn't find native for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10556 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11557 }
[email protected]58e10452012-02-22 03:34:45558 return i->second->NewInstance();
559}
[email protected]ecde1912012-03-16 06:25:31560
[email protected]d9f51dad2014-07-09 05:39:38561void ModuleSystem::RequireAsync(
562 const v8::FunctionCallbackInfo<v8::Value>& args) {
563 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07564 std::string module_name = *v8::String::Utf8Value(args[0]);
bashi6a4854f2015-06-19 00:51:51565 v8::Local<v8::Context> v8_context = context_->v8_context();
tfarinaf85316f2015-04-29 17:03:40566 v8::Local<v8::Promise::Resolver> resolver(
bashi6a4854f2015-06-19 00:51:51567 v8::Promise::Resolver::New(v8_context).ToLocalChecked());
[email protected]d9f51dad2014-07-09 05:39:38568 args.GetReturnValue().Set(resolver->GetPromise());
kalman83292b82015-03-12 16:40:25569 scoped_ptr<v8::Global<v8::Promise::Resolver>> global_resolver(
570 new v8::Global<v8::Promise::Resolver>(GetIsolate(), resolver));
[email protected]d9f51dad2014-07-09 05:39:38571 gin::ModuleRegistry* module_registry =
bashi6a4854f2015-06-19 00:51:51572 gin::ModuleRegistry::From(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38573 if (!module_registry) {
574 Warn(GetIsolate(), "Extension view no longer exists");
bashi6a4854f2015-06-19 00:51:51575 resolver->Reject(v8_context, v8::Exception::Error(ToV8StringUnsafe(
[email protected]d9f51dad2014-07-09 05:39:38576 GetIsolate(), "Extension view no longer exists")));
577 return;
578 }
kalman83292b82015-03-12 16:40:25579 module_registry->LoadModule(
580 GetIsolate(), module_name,
581 base::Bind(&ModuleSystem::OnModuleLoaded, weak_factory_.GetWeakPtr(),
582 base::Passed(&global_resolver)));
[email protected]d9f51dad2014-07-09 05:39:38583 if (module_registry->available_modules().count(module_name) == 0)
584 LoadModule(module_name);
585}
586
tfarinaf85316f2015-04-29 17:03:40587v8::Local<v8::String> ModuleSystem::WrapSource(v8::Local<v8::String> source) {
[email protected]95c6b3012013-12-02 14:30:31588 v8::EscapableHandleScope handle_scope(GetIsolate());
[email protected]295890bd2013-06-15 10:52:45589 // Keep in order with the arguments in RequireForJsInner.
bashi6a4854f2015-06-19 00:51:51590 v8::Local<v8::String> left = ToV8StringUnsafe(
[email protected]2a356872014-02-21 23:18:52591 GetIsolate(),
[email protected]d9f51dad2014-07-09 05:39:38592 "(function(define, require, requireNative, requireAsync, exports, "
[email protected]2a356872014-02-21 23:18:52593 "console, privates,"
[email protected]0d775c72014-08-22 13:06:26594 "$Array, $Function, $JSON, $Object, $RegExp, $String, $Error) {"
[email protected]2a356872014-02-21 23:18:52595 "'use strict';");
bashi6a4854f2015-06-19 00:51:51596 v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})");
[email protected]95c6b3012013-12-02 14:30:31597 return handle_scope.Escape(v8::Local<v8::String>(
598 v8::String::Concat(left, v8::String::Concat(source, right))));
[email protected]ecde1912012-03-16 06:25:31599}
600
[email protected]ca557292013-12-11 08:44:27601void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) {
602 CHECK_EQ(1, args.Length());
rob5c641ed2014-12-09 00:24:57603 if (!args[0]->IsObject() || args[0]->IsNull()) {
604 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51605 v8::Exception::TypeError(ToV8StringUnsafe(GetIsolate(),
rob5c641ed2014-12-09 00:24:57606 args[0]->IsUndefined()
607 ? "Method called without a valid receiver (this). "
608 "Did you forget to call .bind()?"
609 : "Invalid invocation: receiver is not an object!")));
610 return;
611 }
[email protected]ca557292013-12-11 08:44:27612 v8::Local<v8::Object> obj = args[0].As<v8::Object>();
jochen300abe232015-11-06 21:17:53613 v8::Local<v8::Value> privates;
614 if (!GetPrivate(obj, "privates", &privates) || !privates->IsObject()) {
[email protected]505ffde2013-12-19 15:47:13615 privates = v8::Object::New(args.GetIsolate());
kalmanad8ddd02014-10-15 00:20:06616 if (privates.IsEmpty()) {
617 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51618 ToV8StringUnsafe(GetIsolate(), "Failed to create privates"));
kalmanad8ddd02014-10-15 00:20:06619 return;
620 }
jochen300abe232015-11-06 21:17:53621 SetPrivate(obj, "privates", privates);
[email protected]ca557292013-12-11 08:44:27622 }
623 args.GetReturnValue().Set(privates);
624}
625
tfarinaf85316f2015-04-29 17:03:40626v8::Local<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) {
[email protected]d9f51dad2014-07-09 05:39:38627 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51628 v8::Local<v8::Context> v8_context = context()->v8_context();
629 v8::Context::Scope context_scope(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38630
tfarinaf85316f2015-04-29 17:03:40631 v8::Local<v8::Value> source(GetSource(module_name));
[email protected]d9f51dad2014-07-09 05:39:38632 if (source.IsEmpty() || source->IsUndefined()) {
633 Fatal(context_, "No source for require(" + module_name + ")");
634 return v8::Undefined(GetIsolate());
635 }
tfarinaf85316f2015-04-29 17:03:40636 v8::Local<v8::String> wrapped_source(
637 WrapSource(v8::Local<v8::String>::Cast(source)));
bashi6a4854f2015-06-19 00:51:51638 v8::Local<v8::String> v8_module_name;
639 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name)) {
640 NOTREACHED() << "module_name is too long";
641 return v8::Undefined(GetIsolate());
642 }
[email protected]d9f51dad2014-07-09 05:39:38643 // Modules are wrapped in (function(){...}) so they always return functions.
tfarinaf85316f2015-04-29 17:03:40644 v8::Local<v8::Value> func_as_value =
bashi6a4854f2015-06-19 00:51:51645 RunString(wrapped_source, v8_module_name);
[email protected]d9f51dad2014-07-09 05:39:38646 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
647 Fatal(context_, "Bad source for require(" + module_name + ")");
648 return v8::Undefined(GetIsolate());
649 }
650
tfarinaf85316f2015-04-29 17:03:40651 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(func_as_value);
[email protected]d9f51dad2014-07-09 05:39:38652
tfarinaf85316f2015-04-29 17:03:40653 v8::Local<v8::Object> define_object = v8::Object::New(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38654 gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object);
655
rdevlin.cronin83a4b3a2015-10-28 21:43:58656 v8::Local<v8::Object> exports = v8::Object::New(GetIsolate());
657
658 v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(
659 GetIsolate(),
660 &SetExportsProperty);
661 v8::Local<v8::String> v8_key;
662 if (!v8_helpers::ToV8String(GetIsolate(), "$set", &v8_key)) {
663 NOTREACHED();
664 return v8::Undefined(GetIsolate());
665 }
666
667 v8::Local<v8::Function> function;
668 if (!tmpl->GetFunction(v8_context).ToLocal(&function)) {
669 NOTREACHED();
670 return v8::Undefined(GetIsolate());
671 }
672
673 exports->ForceSet(v8_key, function, v8::ReadOnly);
674
tfarinaf85316f2015-04-29 17:03:40675 v8::Local<v8::Object> natives(NewInstance());
bashi6a4854f2015-06-19 00:51:51676 CHECK(!natives.IsEmpty()); // this can fail if v8 has issues
[email protected]d9f51dad2014-07-09 05:39:38677
678 // These must match the argument order in WrapSource.
tfarinaf85316f2015-04-29 17:03:40679 v8::Local<v8::Value> args[] = {
[email protected]d9f51dad2014-07-09 05:39:38680 // AMD.
bashi6a4854f2015-06-19 00:51:51681 GetPropertyUnsafe(v8_context, define_object, "define"),
[email protected]d9f51dad2014-07-09 05:39:38682 // CommonJS.
bashi6a4854f2015-06-19 00:51:51683 GetPropertyUnsafe(v8_context, natives, "require",
684 v8::NewStringType::kInternalized),
685 GetPropertyUnsafe(v8_context, natives, "requireNative",
686 v8::NewStringType::kInternalized),
687 GetPropertyUnsafe(v8_context, natives, "requireAsync",
688 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38689 exports,
690 // Libraries that we magically expose to every module.
kalmanfb6f10ac2014-11-06 23:55:35691 console::AsV8Object(GetIsolate()),
bashi6a4854f2015-06-19 00:51:51692 GetPropertyUnsafe(v8_context, natives, "privates",
693 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38694 // Each safe builtin. Keep in order with the arguments in WrapSource.
695 context_->safe_builtins()->GetArray(),
696 context_->safe_builtins()->GetFunction(),
697 context_->safe_builtins()->GetJSON(),
698 context_->safe_builtins()->GetObjekt(),
699 context_->safe_builtins()->GetRegExp(),
700 context_->safe_builtins()->GetString(),
[email protected]0d775c72014-08-22 13:06:26701 context_->safe_builtins()->GetError(),
[email protected]d9f51dad2014-07-09 05:39:38702 };
703 {
bashi6a4854f2015-06-19 00:51:51704 v8::TryCatch try_catch(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38705 try_catch.SetCaptureMessage(true);
706 context_->CallFunction(func, arraysize(args), args);
707 if (try_catch.HasCaught()) {
708 HandleException(try_catch);
709 return v8::Undefined(GetIsolate());
710 }
711 }
712 return handle_scope.Escape(exports);
713}
714
715void ModuleSystem::OnDidAddPendingModule(
716 const std::string& id,
717 const std::vector<std::string>& dependencies) {
sammc2cc226562015-01-14 01:25:06718 bool module_system_managed = source_map_->Contains(id);
[email protected]d9f51dad2014-07-09 05:39:38719
720 gin::ModuleRegistry* registry =
721 gin::ModuleRegistry::From(context_->v8_context());
722 DCHECK(registry);
sammc2cc226562015-01-14 01:25:06723 for (const auto& dependency : dependencies) {
724 // If a dependency is not available, and either the module or this
725 // dependency is managed by ModuleSystem, attempt to load it. Other
726 // gin::ModuleRegistry users (WebUI and users of the mojoPrivate API) are
727 // responsible for loading their module dependencies when required.
728 if (registry->available_modules().count(dependency) == 0 &&
729 (module_system_managed || source_map_->Contains(dependency))) {
730 LoadModule(dependency);
731 }
[email protected]d9f51dad2014-07-09 05:39:38732 }
733 registry->AttemptToLoadMoreModules(GetIsolate());
734}
735
736void ModuleSystem::OnModuleLoaded(
kalman83292b82015-03-12 16:40:25737 scoped_ptr<v8::Global<v8::Promise::Resolver>> resolver,
tfarinaf85316f2015-04-29 17:03:40738 v8::Local<v8::Value> value) {
[email protected]d9f51dad2014-07-09 05:39:38739 if (!is_valid())
740 return;
741 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40742 v8::Local<v8::Promise::Resolver> resolver_local(
[email protected]d9f51dad2014-07-09 05:39:38743 v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver));
bashi6a4854f2015-06-19 00:51:51744 resolver_local->Resolve(context()->v8_context(), value);
[email protected]d9f51dad2014-07-09 05:39:38745}
746
kalmanb0c1c502015-04-15 00:25:06747void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) {
748 NativeHandlerMap::iterator existing_handler = native_handler_map_.find(name);
749 if (existing_handler != native_handler_map_.end()) {
750 clobbered_native_handlers_.push_back(existing_handler->second);
751 native_handler_map_.erase(existing_handler);
752 }
753}
754
[email protected]4e008e172013-06-13 20:15:48755} // namespace extensions