blob: 923418af870f08e643b7234f2279cd4a356148e1 [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);
tzik8f7af2922015-11-25 03:16:48341 native_handler_map_[name] = std::move(native_handler);
[email protected]58e10452012-02-22 03:34:45342}
343
[email protected]95ee77da2013-03-19 21:11:11344void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) {
kalmanb0c1c502015-04-15 00:25:06345 ClobberExistingNativeHandler(name);
[email protected]11844fa2012-05-10 00:35:59346 overridden_native_handlers_.insert(name);
347}
348
[email protected]ecde1912012-03-16 06:25:31349void ModuleSystem::RunString(const std::string& code, const std::string& name) {
[email protected]dc3d06e2013-09-06 12:21:03350 v8::HandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51351 v8::Local<v8::String> v8_code;
352 v8::Local<v8::String> v8_name;
353 if (!ToV8String(GetIsolate(), code.c_str(), &v8_code) ||
354 !ToV8String(GetIsolate(), name.c_str(), &v8_name)) {
355 Warn(GetIsolate(), "Too long code or name.");
356 return;
357 }
358 RunString(v8_code, v8_name);
[email protected]58e10452012-02-22 03:34:45359}
360
[email protected]cc0457712012-03-21 03:56:38361// static
[email protected]4e008e172013-06-13 20:15:48362void ModuleSystem::NativeLazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51363 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48364 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51365 LazyFieldGetterInner(property.As<v8::String>(), info,
366 &ModuleSystem::RequireNativeFromString);
[email protected]4e008e172013-06-13 20:15:48367}
368
369// static
370void ModuleSystem::LazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51371 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48372 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51373 LazyFieldGetterInner(property.As<v8::String>(), info, &ModuleSystem::Require);
[email protected]4e008e172013-06-13 20:15:48374}
375
376// static
377void ModuleSystem::LazyFieldGetterInner(
378 v8::Local<v8::String> property,
379 const v8::PropertyCallbackInfo<v8::Value>& info,
[email protected]4f1633f2013-03-09 14:26:24380 RequireFunction require_function) {
[email protected]561ddce2012-03-22 01:18:55381 CHECK(!info.Data().IsEmpty());
382 CHECK(info.Data()->IsObject());
jochen300abe232015-11-06 21:17:53383 v8::Isolate* isolate = info.GetIsolate();
384 v8::HandleScope handle_scope(isolate);
tfarinaf85316f2015-04-29 17:03:40385 v8::Local<v8::Object> parameters = v8::Local<v8::Object>::Cast(info.Data());
[email protected]9a598442013-06-04 16:39:12386 // This context should be the same as context()->v8_context().
tfarinaf85316f2015-04-29 17:03:40387 v8::Local<v8::Context> context = parameters->CreationContext();
388 v8::Local<v8::Object> global(context->Global());
jochen300abe232015-11-06 21:17:53389 v8::Local<v8::Value> module_system_value;
390 if (!GetPrivate(context, global, kModuleSystem, &module_system_value) ||
391 !module_system_value->IsExternal()) {
[email protected]bad9a5f2012-04-13 19:16:54392 // ModuleSystem has been deleted.
[email protected]95ee77da2013-03-19 21:11:11393 // TODO(kalman): See comment in header file.
jochen300abe232015-11-06 21:17:53394 Warn(isolate,
[email protected]95c6b3012013-12-02 14:30:31395 "Module system has been deleted, does extension view exist?");
[email protected]4e008e172013-06-13 20:15:48396 return;
[email protected]bad9a5f2012-04-13 19:16:54397 }
[email protected]95ee77da2013-03-19 21:11:11398
[email protected]561ddce2012-03-22 01:18:55399 ModuleSystem* module_system = static_cast<ModuleSystem*>(
tfarinaf85316f2015-04-29 17:03:40400 v8::Local<v8::External>::Cast(module_system_value)->Value());
[email protected]cc0457712012-03-21 03:56:38401
bashi6a4854f2015-06-19 00:51:51402 v8::Local<v8::Value> v8_module_name;
403 if (!GetProperty(context, parameters, kModuleName, &v8_module_name)) {
jochen300abe232015-11-06 21:17:53404 Warn(isolate, "Cannot find module.");
bashi6a4854f2015-06-19 00:51:51405 return;
406 }
407 std::string name = *v8::String::Utf8Value(v8_module_name);
[email protected]4f1633f2013-03-09 14:26:24408
409 // Switch to our v8 context because we need functions created while running
410 // the require()d module to belong to our context, not the current one.
411 v8::Context::Scope context_scope(context);
412 NativesEnabledScope natives_enabled_scope(module_system);
413
jochen300abe232015-11-06 21:17:53414 v8::TryCatch try_catch(isolate);
bashi61ca3c72015-06-26 00:40:10415 v8::Local<v8::Value> module_value;
416 if (!(module_system->*require_function)(name).ToLocal(&module_value)) {
[email protected]4f1633f2013-03-09 14:26:24417 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48418 return;
[email protected]95ee77da2013-03-19 21:11:11419 }
[email protected]4f1633f2013-03-09 14:26:24420
tfarinaf85316f2015-04-29 17:03:40421 v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(module_value);
bashi6a4854f2015-06-19 00:51:51422 v8::Local<v8::Value> field_value;
423 if (!GetProperty(context, parameters, kModuleField, &field_value)) {
424 module_system->HandleException(try_catch);
425 return;
426 }
427 v8::Local<v8::String> field;
428 if (!field_value->ToString(context).ToLocal(&field)) {
429 module_system->HandleException(try_catch);
430 return;
431 }
[email protected]561ddce2012-03-22 01:18:55432
bashi6a4854f2015-06-19 00:51:51433 if (!IsTrue(module->Has(context, field))) {
[email protected]d7cd1b02013-09-10 00:22:16434 std::string field_str = *v8::String::Utf8Value(field);
[email protected]662c48b2013-07-12 03:50:52435 Fatal(module_system->context_,
436 "Lazy require of " + name + "." + field_str + " did not set the " +
437 field_str + " field");
[email protected]4e008e172013-06-13 20:15:48438 return;
[email protected]95ee77da2013-03-19 21:11:11439 }
[email protected]4f1633f2013-03-09 14:26:24440
bashi6a4854f2015-06-19 00:51:51441 v8::Local<v8::Value> new_field;
442 if (!GetProperty(context, module, field, &new_field)) {
[email protected]95ee77da2013-03-19 21:11:11443 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48444 return;
[email protected]95ee77da2013-03-19 21:11:11445 }
446
447 // Ok for it to be undefined, among other things it's how bindings signify
448 // that the extension doesn't have permission to use them.
449 CHECK(!new_field.IsEmpty());
450
[email protected]4f1633f2013-03-09 14:26:24451 // Delete the getter and set this field to |new_field| so the same object is
452 // returned every time a certain API is accessed.
tfarinaf85316f2015-04-29 17:03:40453 v8::Local<v8::Value> val = info.This();
[email protected]80b0c8c2014-04-22 15:00:43454 if (val->IsObject()) {
tfarinaf85316f2015-04-29 17:03:40455 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(val);
bashi6a4854f2015-06-19 00:51:51456 object->Delete(context, property);
457 SetProperty(context, object, property, new_field);
[email protected]80b0c8c2014-04-22 15:00:43458 } else {
459 NOTREACHED();
460 }
[email protected]4e008e172013-06-13 20:15:48461 info.GetReturnValue().Set(new_field);
[email protected]561ddce2012-03-22 01:18:55462}
463
tfarinaf85316f2015-04-29 17:03:40464void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]561ddce2012-03-22 01:18:55465 const std::string& field,
466 const std::string& module_name,
467 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03468 SetLazyField(
469 object, field, module_name, module_field, &ModuleSystem::LazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24470}
471
tfarinaf85316f2015-04-29 17:03:40472void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24473 const std::string& field,
474 const std::string& module_name,
475 const std::string& module_field,
bashi6a4854f2015-06-19 00:51:51476 v8::AccessorNameGetterCallback getter) {
477 CHECK(field.size() < v8::String::kMaxLength);
478 CHECK(module_name.size() < v8::String::kMaxLength);
479 CHECK(module_field.size() < v8::String::kMaxLength);
[email protected]dc3d06e2013-09-06 12:21:03480 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40481 v8::Local<v8::Object> parameters = v8::Object::New(GetIsolate());
bashi6a4854f2015-06-19 00:51:51482 v8::Local<v8::Context> context = context_->v8_context();
483 SetProperty(context, parameters, kModuleName,
484 ToV8StringUnsafe(GetIsolate(), module_name.c_str()));
485 SetProperty(context, parameters, kModuleField,
486 ToV8StringUnsafe(GetIsolate(), module_field.c_str()));
487 auto maybe = object->SetAccessor(
488 context, ToV8StringUnsafe(GetIsolate(), field.c_str()), getter, NULL,
489 parameters);
490 CHECK(IsTrue(maybe));
[email protected]cc0457712012-03-21 03:56:38491}
[email protected]ecde1912012-03-16 06:25:31492
tfarinaf85316f2015-04-29 17:03:40493void ModuleSystem::SetNativeLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24494 const std::string& field,
495 const std::string& module_name,
496 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03497 SetLazyField(object,
498 field,
499 module_name,
500 module_field,
501 &ModuleSystem::NativeLazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24502}
503
tfarinaf85316f2015-04-29 17:03:40504v8::Local<v8::Value> ModuleSystem::RunString(v8::Local<v8::String> code,
505 v8::Local<v8::String> name) {
annekao533482222015-08-21 23:23:53506 return context_->RunScript(
507 name, code, base::Bind(&ExceptionHandler::HandleUncaughtException,
508 base::Unretained(exception_handler_.get())));
[email protected]9e03ce22012-03-13 08:50:05509}
510
tfarinaf85316f2015-04-29 17:03:40511v8::Local<v8::Value> ModuleSystem::GetSource(const std::string& module_name) {
[email protected]95c6b3012013-12-02 14:30:31512 v8::EscapableHandleScope handle_scope(GetIsolate());
[email protected]ecde1912012-03-16 06:25:31513 if (!source_map_->Contains(module_name))
[email protected]95c6b3012013-12-02 14:30:31514 return v8::Undefined(GetIsolate());
515 return handle_scope.Escape(
516 v8::Local<v8::Value>(source_map_->GetSource(GetIsolate(), module_name)));
[email protected]58e10452012-02-22 03:34:45517}
518
[email protected]d8c5fbb2013-06-14 11:35:25519void ModuleSystem::RequireNative(
520 const v8::FunctionCallbackInfo<v8::Value>& args) {
[email protected]58e10452012-02-22 03:34:45521 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07522 std::string native_name = *v8::String::Utf8Value(args[0]);
bashi61ca3c72015-06-26 00:40:10523 v8::Local<v8::Object> object;
524 if (RequireNativeFromString(native_name).ToLocal(&object))
525 args.GetReturnValue().Set(object);
[email protected]4f1633f2013-03-09 14:26:24526}
527
bashi61ca3c72015-06-26 00:40:10528v8::MaybeLocal<v8::Object> ModuleSystem::RequireNativeFromString(
[email protected]4f1633f2013-03-09 14:26:24529 const std::string& native_name) {
[email protected]95ee77da2013-03-19 21:11:11530 if (natives_enabled_ == 0) {
531 // HACK: if in test throw exception so that we can test the natives-disabled
532 // logic; however, under normal circumstances, this is programmer error so
533 // we could crash.
[email protected]9c47471e2013-11-28 14:41:21534 if (exception_handler_) {
bashi61ca3c72015-06-26 00:40:10535 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51536 ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
bashi61ca3c72015-06-26 00:40:10537 return v8::MaybeLocal<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21538 }
[email protected]662c48b2013-07-12 03:50:52539 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10540 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11541 }
542
[email protected]9c47471e2013-11-28 14:41:21543 if (overridden_native_handlers_.count(native_name) > 0u) {
bashi61ca3c72015-06-26 00:40:10544 v8::Local<v8::Value> value = RequireForJsInner(
bashi6a4854f2015-06-19 00:51:51545 ToV8StringUnsafe(GetIsolate(), native_name.c_str()));
bashi61ca3c72015-06-26 00:40:10546 if (value.IsEmpty() || !value->IsObject())
547 return v8::MaybeLocal<v8::Object>();
548 return value.As<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21549 }
[email protected]95ee77da2013-03-19 21:11:11550
[email protected]58e10452012-02-22 03:34:45551 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
[email protected]95ee77da2013-03-19 21:11:11552 if (i == native_handler_map_.end()) {
[email protected]662c48b2013-07-12 03:50:52553 Fatal(context_,
[email protected]ad6aa8f92013-06-22 15:34:16554 "Couldn't find native for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10555 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11556 }
[email protected]58e10452012-02-22 03:34:45557 return i->second->NewInstance();
558}
[email protected]ecde1912012-03-16 06:25:31559
[email protected]d9f51dad2014-07-09 05:39:38560void ModuleSystem::RequireAsync(
561 const v8::FunctionCallbackInfo<v8::Value>& args) {
562 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07563 std::string module_name = *v8::String::Utf8Value(args[0]);
bashi6a4854f2015-06-19 00:51:51564 v8::Local<v8::Context> v8_context = context_->v8_context();
tfarinaf85316f2015-04-29 17:03:40565 v8::Local<v8::Promise::Resolver> resolver(
bashi6a4854f2015-06-19 00:51:51566 v8::Promise::Resolver::New(v8_context).ToLocalChecked());
[email protected]d9f51dad2014-07-09 05:39:38567 args.GetReturnValue().Set(resolver->GetPromise());
kalman83292b82015-03-12 16:40:25568 scoped_ptr<v8::Global<v8::Promise::Resolver>> global_resolver(
569 new v8::Global<v8::Promise::Resolver>(GetIsolate(), resolver));
[email protected]d9f51dad2014-07-09 05:39:38570 gin::ModuleRegistry* module_registry =
bashi6a4854f2015-06-19 00:51:51571 gin::ModuleRegistry::From(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38572 if (!module_registry) {
573 Warn(GetIsolate(), "Extension view no longer exists");
bashi6a4854f2015-06-19 00:51:51574 resolver->Reject(v8_context, v8::Exception::Error(ToV8StringUnsafe(
[email protected]d9f51dad2014-07-09 05:39:38575 GetIsolate(), "Extension view no longer exists")));
576 return;
577 }
kalman83292b82015-03-12 16:40:25578 module_registry->LoadModule(
579 GetIsolate(), module_name,
580 base::Bind(&ModuleSystem::OnModuleLoaded, weak_factory_.GetWeakPtr(),
581 base::Passed(&global_resolver)));
[email protected]d9f51dad2014-07-09 05:39:38582 if (module_registry->available_modules().count(module_name) == 0)
583 LoadModule(module_name);
584}
585
tfarinaf85316f2015-04-29 17:03:40586v8::Local<v8::String> ModuleSystem::WrapSource(v8::Local<v8::String> source) {
[email protected]95c6b3012013-12-02 14:30:31587 v8::EscapableHandleScope handle_scope(GetIsolate());
[email protected]295890bd2013-06-15 10:52:45588 // Keep in order with the arguments in RequireForJsInner.
bashi6a4854f2015-06-19 00:51:51589 v8::Local<v8::String> left = ToV8StringUnsafe(
[email protected]2a356872014-02-21 23:18:52590 GetIsolate(),
[email protected]d9f51dad2014-07-09 05:39:38591 "(function(define, require, requireNative, requireAsync, exports, "
[email protected]2a356872014-02-21 23:18:52592 "console, privates,"
[email protected]0d775c72014-08-22 13:06:26593 "$Array, $Function, $JSON, $Object, $RegExp, $String, $Error) {"
[email protected]2a356872014-02-21 23:18:52594 "'use strict';");
bashi6a4854f2015-06-19 00:51:51595 v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})");
[email protected]95c6b3012013-12-02 14:30:31596 return handle_scope.Escape(v8::Local<v8::String>(
597 v8::String::Concat(left, v8::String::Concat(source, right))));
[email protected]ecde1912012-03-16 06:25:31598}
599
[email protected]ca557292013-12-11 08:44:27600void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) {
601 CHECK_EQ(1, args.Length());
rob5c641ed2014-12-09 00:24:57602 if (!args[0]->IsObject() || args[0]->IsNull()) {
603 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51604 v8::Exception::TypeError(ToV8StringUnsafe(GetIsolate(),
rob5c641ed2014-12-09 00:24:57605 args[0]->IsUndefined()
606 ? "Method called without a valid receiver (this). "
607 "Did you forget to call .bind()?"
608 : "Invalid invocation: receiver is not an object!")));
609 return;
610 }
[email protected]ca557292013-12-11 08:44:27611 v8::Local<v8::Object> obj = args[0].As<v8::Object>();
jochen300abe232015-11-06 21:17:53612 v8::Local<v8::Value> privates;
613 if (!GetPrivate(obj, "privates", &privates) || !privates->IsObject()) {
[email protected]505ffde2013-12-19 15:47:13614 privates = v8::Object::New(args.GetIsolate());
kalmanad8ddd02014-10-15 00:20:06615 if (privates.IsEmpty()) {
616 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51617 ToV8StringUnsafe(GetIsolate(), "Failed to create privates"));
kalmanad8ddd02014-10-15 00:20:06618 return;
619 }
jochen300abe232015-11-06 21:17:53620 SetPrivate(obj, "privates", privates);
[email protected]ca557292013-12-11 08:44:27621 }
622 args.GetReturnValue().Set(privates);
623}
624
tfarinaf85316f2015-04-29 17:03:40625v8::Local<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) {
[email protected]d9f51dad2014-07-09 05:39:38626 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51627 v8::Local<v8::Context> v8_context = context()->v8_context();
628 v8::Context::Scope context_scope(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38629
tfarinaf85316f2015-04-29 17:03:40630 v8::Local<v8::Value> source(GetSource(module_name));
[email protected]d9f51dad2014-07-09 05:39:38631 if (source.IsEmpty() || source->IsUndefined()) {
632 Fatal(context_, "No source for require(" + module_name + ")");
633 return v8::Undefined(GetIsolate());
634 }
tfarinaf85316f2015-04-29 17:03:40635 v8::Local<v8::String> wrapped_source(
636 WrapSource(v8::Local<v8::String>::Cast(source)));
bashi6a4854f2015-06-19 00:51:51637 v8::Local<v8::String> v8_module_name;
638 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name)) {
639 NOTREACHED() << "module_name is too long";
640 return v8::Undefined(GetIsolate());
641 }
[email protected]d9f51dad2014-07-09 05:39:38642 // Modules are wrapped in (function(){...}) so they always return functions.
tfarinaf85316f2015-04-29 17:03:40643 v8::Local<v8::Value> func_as_value =
bashi6a4854f2015-06-19 00:51:51644 RunString(wrapped_source, v8_module_name);
[email protected]d9f51dad2014-07-09 05:39:38645 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
646 Fatal(context_, "Bad source for require(" + module_name + ")");
647 return v8::Undefined(GetIsolate());
648 }
649
tfarinaf85316f2015-04-29 17:03:40650 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(func_as_value);
[email protected]d9f51dad2014-07-09 05:39:38651
tfarinaf85316f2015-04-29 17:03:40652 v8::Local<v8::Object> define_object = v8::Object::New(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38653 gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object);
654
rdevlin.cronin83a4b3a2015-10-28 21:43:58655 v8::Local<v8::Object> exports = v8::Object::New(GetIsolate());
656
657 v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(
658 GetIsolate(),
659 &SetExportsProperty);
660 v8::Local<v8::String> v8_key;
661 if (!v8_helpers::ToV8String(GetIsolate(), "$set", &v8_key)) {
662 NOTREACHED();
663 return v8::Undefined(GetIsolate());
664 }
665
666 v8::Local<v8::Function> function;
667 if (!tmpl->GetFunction(v8_context).ToLocal(&function)) {
668 NOTREACHED();
669 return v8::Undefined(GetIsolate());
670 }
671
672 exports->ForceSet(v8_key, function, v8::ReadOnly);
673
tfarinaf85316f2015-04-29 17:03:40674 v8::Local<v8::Object> natives(NewInstance());
bashi6a4854f2015-06-19 00:51:51675 CHECK(!natives.IsEmpty()); // this can fail if v8 has issues
[email protected]d9f51dad2014-07-09 05:39:38676
677 // These must match the argument order in WrapSource.
tfarinaf85316f2015-04-29 17:03:40678 v8::Local<v8::Value> args[] = {
[email protected]d9f51dad2014-07-09 05:39:38679 // AMD.
bashi6a4854f2015-06-19 00:51:51680 GetPropertyUnsafe(v8_context, define_object, "define"),
[email protected]d9f51dad2014-07-09 05:39:38681 // CommonJS.
bashi6a4854f2015-06-19 00:51:51682 GetPropertyUnsafe(v8_context, natives, "require",
683 v8::NewStringType::kInternalized),
684 GetPropertyUnsafe(v8_context, natives, "requireNative",
685 v8::NewStringType::kInternalized),
686 GetPropertyUnsafe(v8_context, natives, "requireAsync",
687 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38688 exports,
689 // Libraries that we magically expose to every module.
kalmanfb6f10ac2014-11-06 23:55:35690 console::AsV8Object(GetIsolate()),
bashi6a4854f2015-06-19 00:51:51691 GetPropertyUnsafe(v8_context, natives, "privates",
692 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38693 // Each safe builtin. Keep in order with the arguments in WrapSource.
694 context_->safe_builtins()->GetArray(),
695 context_->safe_builtins()->GetFunction(),
696 context_->safe_builtins()->GetJSON(),
697 context_->safe_builtins()->GetObjekt(),
698 context_->safe_builtins()->GetRegExp(),
699 context_->safe_builtins()->GetString(),
[email protected]0d775c72014-08-22 13:06:26700 context_->safe_builtins()->GetError(),
[email protected]d9f51dad2014-07-09 05:39:38701 };
702 {
bashi6a4854f2015-06-19 00:51:51703 v8::TryCatch try_catch(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38704 try_catch.SetCaptureMessage(true);
705 context_->CallFunction(func, arraysize(args), args);
706 if (try_catch.HasCaught()) {
707 HandleException(try_catch);
708 return v8::Undefined(GetIsolate());
709 }
710 }
711 return handle_scope.Escape(exports);
712}
713
714void ModuleSystem::OnDidAddPendingModule(
715 const std::string& id,
716 const std::vector<std::string>& dependencies) {
sammc2cc226562015-01-14 01:25:06717 bool module_system_managed = source_map_->Contains(id);
[email protected]d9f51dad2014-07-09 05:39:38718
719 gin::ModuleRegistry* registry =
720 gin::ModuleRegistry::From(context_->v8_context());
721 DCHECK(registry);
sammc2cc226562015-01-14 01:25:06722 for (const auto& dependency : dependencies) {
723 // If a dependency is not available, and either the module or this
724 // dependency is managed by ModuleSystem, attempt to load it. Other
725 // gin::ModuleRegistry users (WebUI and users of the mojoPrivate API) are
726 // responsible for loading their module dependencies when required.
727 if (registry->available_modules().count(dependency) == 0 &&
728 (module_system_managed || source_map_->Contains(dependency))) {
729 LoadModule(dependency);
730 }
[email protected]d9f51dad2014-07-09 05:39:38731 }
732 registry->AttemptToLoadMoreModules(GetIsolate());
733}
734
735void ModuleSystem::OnModuleLoaded(
kalman83292b82015-03-12 16:40:25736 scoped_ptr<v8::Global<v8::Promise::Resolver>> resolver,
tfarinaf85316f2015-04-29 17:03:40737 v8::Local<v8::Value> value) {
[email protected]d9f51dad2014-07-09 05:39:38738 if (!is_valid())
739 return;
740 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40741 v8::Local<v8::Promise::Resolver> resolver_local(
[email protected]d9f51dad2014-07-09 05:39:38742 v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver));
bashi6a4854f2015-06-19 00:51:51743 resolver_local->Resolve(context()->v8_context(), value);
[email protected]d9f51dad2014-07-09 05:39:38744}
745
kalmanb0c1c502015-04-15 00:25:06746void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) {
747 NativeHandlerMap::iterator existing_handler = native_handler_map_.find(name);
748 if (existing_handler != native_handler_map_.end()) {
tzik8f7af2922015-11-25 03:16:48749 clobbered_native_handlers_.push_back(std::move(existing_handler->second));
kalmanb0c1c502015-04-15 00:25:06750 native_handler_map_.erase(existing_handler);
751 }
752}
753
[email protected]4e008e172013-06-13 20:15:48754} // namespace extensions