blob: 96f79cbb59b332185667393287687da0e04e81fb [file] [log] [blame]
[email protected]58e10452012-02-22 03:34:451// Copyright (c) 2012 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 "chrome/renderer/module_system.h"
6
7#include "base/bind.h"
[email protected]58e10452012-02-22 03:34:458
9namespace {
10
[email protected]58e10452012-02-22 03:34:4511} // namespace
12
[email protected]ecde1912012-03-16 06:25:3113ModuleSystem::ModuleSystem(SourceMap* source_map)
14 : source_map_(source_map),
15 natives_enabled_(true) {
16 RouteFunction("require",
17 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this)));
18 RouteFunction("requireNative",
[email protected]58e10452012-02-22 03:34:4519 base::Bind(&ModuleSystem::GetNative, base::Unretained(this)));
[email protected]ecde1912012-03-16 06:25:3120
21 v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global());
22 global->SetHiddenValue(v8::String::New("modules"), v8::Object::New());
[email protected]58e10452012-02-22 03:34:4523}
24
25ModuleSystem::~ModuleSystem() {
26}
27
28void ModuleSystem::Require(const std::string& module_name) {
[email protected]58e10452012-02-22 03:34:4529 v8::HandleScope handle_scope;
[email protected]ecde1912012-03-16 06:25:3130 RequireForJsInner(v8::String::New(module_name.c_str()));
31}
32
33v8::Handle<v8::Value> ModuleSystem::RequireForJs(const v8::Arguments& args) {
34 v8::HandleScope handle_scope;
35 v8::Handle<v8::String> module_name = args[0]->ToString();
36 return handle_scope.Close(RequireForJsInner(module_name));
37}
38
39v8::Handle<v8::Value> ModuleSystem::RequireForJsInner(
40 v8::Handle<v8::String> module_name) {
41 v8::HandleScope handle_scope;
42 v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global());
43 v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast(
44 global->GetHiddenValue(v8::String::New("modules"))));
45 v8::Handle<v8::Value> exports(modules->Get(module_name));
46 if (!exports->IsUndefined())
47 return handle_scope.Close(exports);
48 v8::Handle<v8::Value> source(GetSource(module_name));
49 if (source->IsUndefined())
50 return handle_scope.Close(v8::Undefined());
51 v8::Handle<v8::String> wrapped_source(WrapSource(
52 v8::Handle<v8::String>::Cast(source)));
53 v8::Handle<v8::Function> func =
54 v8::Handle<v8::Function>::Cast(RunString(wrapped_source, module_name));
55 exports = v8::Object::New();
56 v8::Handle<v8::Object> natives(NewInstance());
57 v8::Handle<v8::Value> args[] = {
58 natives->Get(v8::String::NewSymbol("require")),
59 natives->Get(v8::String::NewSymbol("requireNative")),
60 exports,
[email protected]58e10452012-02-22 03:34:4561 };
[email protected]ecde1912012-03-16 06:25:3162 func->Call(global, 3, args);
63 modules->Set(module_name, exports);
64 return handle_scope.Close(exports);
[email protected]58e10452012-02-22 03:34:4565}
66
67void ModuleSystem::RegisterNativeHandler(const std::string& name,
68 scoped_ptr<NativeHandler> native_handler) {
69 native_handler_map_[name] =
70 linked_ptr<NativeHandler>(native_handler.release());
71}
72
[email protected]ecde1912012-03-16 06:25:3173void ModuleSystem::RunString(const std::string& code, const std::string& name) {
[email protected]9fb990b2012-03-13 02:09:4174 v8::HandleScope handle_scope;
[email protected]ecde1912012-03-16 06:25:3175 RunString(v8::String::New(code.c_str()), v8::String::New(name.c_str()));
[email protected]58e10452012-02-22 03:34:4576}
77
[email protected]ecde1912012-03-16 06:25:3178
79v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code,
80 v8::Handle<v8::String> name) {
[email protected]58e10452012-02-22 03:34:4581 v8::HandleScope handle_scope;
[email protected]ecde1912012-03-16 06:25:3182 return handle_scope.Close(v8::Script::New(code, name)->Run());
[email protected]9e03ce22012-03-13 08:50:0583}
84
[email protected]ecde1912012-03-16 06:25:3185v8::Handle<v8::Value> ModuleSystem::GetSource(
86 v8::Handle<v8::String> source_name) {
[email protected]9e03ce22012-03-13 08:50:0587 v8::HandleScope handle_scope;
[email protected]ecde1912012-03-16 06:25:3188 std::string module_name = *v8::String::AsciiValue(source_name);
89 if (!source_map_->Contains(module_name))
[email protected]58e10452012-02-22 03:34:4590 return v8::Undefined();
[email protected]ecde1912012-03-16 06:25:3191 return handle_scope.Close(source_map_->GetSource(module_name));
[email protected]58e10452012-02-22 03:34:4592}
93
94v8::Handle<v8::Value> ModuleSystem::GetNative(const v8::Arguments& args) {
95 CHECK_EQ(1, args.Length());
[email protected]ecde1912012-03-16 06:25:3196 if (!natives_enabled_)
97 return ThrowException("Natives disabled");
[email protected]58e10452012-02-22 03:34:4598 std::string native_name = *v8::String::AsciiValue(args[0]->ToString());
99 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
100 if (i == native_handler_map_.end())
101 return v8::Undefined();
102 return i->second->NewInstance();
103}
[email protected]ecde1912012-03-16 06:25:31104
105v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) {
106 v8::HandleScope handle_scope;
107 v8::Handle<v8::String> left =
108 v8::String::New("(function(require, requireNative, exports) {");
109 v8::Handle<v8::String> right = v8::String::New("\n})");
110 return handle_scope.Close(
111 v8::String::Concat(left, v8::String::Concat(source, right)));
112}
113
114v8::Handle<v8::Value> ModuleSystem::ThrowException(const std::string& message) {
115 return v8::ThrowException(v8::String::New(message.c_str()));
116}