summaryrefslogtreecommitdiffstats
path: root/gin/modules
diff options
context:
space:
mode:
Diffstat (limited to 'gin/modules')
-rw-r--r--gin/modules/console.cc4
-rw-r--r--gin/modules/console.h2
-rw-r--r--gin/modules/module_registry.cc7
-rw-r--r--gin/modules/module_registry.h5
-rw-r--r--gin/modules/module_runner_delegate.cc4
-rw-r--r--gin/modules/module_runner_delegate.h12
-rw-r--r--gin/modules/timer.cc95
-rw-r--r--gin/modules/timer.h63
-rw-r--r--gin/modules/timer_unittest.cc124
9 files changed, 295 insertions, 21 deletions
diff --git a/gin/modules/console.cc b/gin/modules/console.cc
index 84c620a..c7b9aeb 100644
--- a/gin/modules/console.cc
+++ b/gin/modules/console.cc
@@ -29,7 +29,7 @@ WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
const char Console::kModuleName[] = "console";
-v8::Local<ObjectTemplate> Console::GetTemplate(v8::Isolate* isolate) {
+v8::Local<v8::Value> Console::GetModule(v8::Isolate* isolate) {
PerIsolateData* data = PerIsolateData::From(isolate);
v8::Local<ObjectTemplate> templ = data->GetObjectTemplate(&g_wrapper_info);
if (templ.IsEmpty()) {
@@ -38,7 +38,7 @@ v8::Local<ObjectTemplate> Console::GetTemplate(v8::Isolate* isolate) {
.Build();
data->SetObjectTemplate(&g_wrapper_info, templ);
}
- return templ;
+ return templ->NewInstance();
}
} // namespace gin
diff --git a/gin/modules/console.h b/gin/modules/console.h
index 8753961..ff8061b 100644
--- a/gin/modules/console.h
+++ b/gin/modules/console.h
@@ -15,7 +15,7 @@ namespace gin {
class GIN_EXPORT Console {
public:
static const char kModuleName[];
- static v8::Local<v8::ObjectTemplate> GetTemplate(v8::Isolate* isolate);
+ static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
};
} // namespace gin
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
index 035c259..eda3488 100644
--- a/gin/modules/module_registry.cc
+++ b/gin/modules/module_registry.cc
@@ -123,11 +123,10 @@ ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) {
return static_cast<ModuleRegistry*>(external->Value());
}
-void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
- const std::string& id,
- v8::Handle<ObjectTemplate> templ) {
+void ModuleRegistry::AddBuiltinModule(Isolate* isolate, const std::string& id,
+ v8::Handle<Value> module) {
DCHECK(!id.empty());
- RegisterModule(isolate, id, templ->NewInstance());
+ RegisterModule(isolate, id, module);
}
void ModuleRegistry::AddPendingModule(Isolate* isolate,
diff --git a/gin/modules/module_registry.h b/gin/modules/module_registry.h
index 27606cd..755875c 100644
--- a/gin/modules/module_registry.h
+++ b/gin/modules/module_registry.h
@@ -43,9 +43,8 @@ class GIN_EXPORT ModuleRegistry : public ContextSupplement {
v8::Handle<v8::ObjectTemplate> templ);
// The caller must have already entered our context.
- void AddBuiltinModule(v8::Isolate* isolate,
- const std::string& id,
- v8::Handle<v8::ObjectTemplate> templ);
+ void AddBuiltinModule(v8::Isolate* isolate, const std::string& id,
+ v8::Handle<v8::Value> module);
// The caller must have already entered our context.
void AddPendingModule(v8::Isolate* isolate,
diff --git a/gin/modules/module_runner_delegate.cc b/gin/modules/module_runner_delegate.cc
index 404f5dc..2a9f95c 100644
--- a/gin/modules/module_runner_delegate.cc
+++ b/gin/modules/module_runner_delegate.cc
@@ -18,8 +18,8 @@ ModuleRunnerDelegate::~ModuleRunnerDelegate() {
}
void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id,
- ModuleTemplateGetter templ) {
- builtin_modules_[id] = templ;
+ ModuleGetter getter) {
+ builtin_modules_[id] = getter;
}
void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) {
diff --git a/gin/modules/module_runner_delegate.h b/gin/modules/module_runner_delegate.h
index 06077f4..3ce056f 100644
--- a/gin/modules/module_runner_delegate.h
+++ b/gin/modules/module_runner_delegate.h
@@ -14,8 +14,7 @@
namespace gin {
-typedef v8::Local<v8::ObjectTemplate> (*ModuleTemplateGetter)(
- v8::Isolate* isolate);
+typedef v8::Local<v8::Value> (*ModuleGetter)(v8::Isolate* isolate);
// Emebedders that use AMD modules will probably want to use a RunnerDelegate
// that inherits from ModuleRunnerDelegate. ModuleRunnerDelegate lets embedders
@@ -26,18 +25,13 @@ class GIN_EXPORT ModuleRunnerDelegate : public RunnerDelegate {
const std::vector<base::FilePath>& search_paths);
virtual ~ModuleRunnerDelegate();
- // Lets you register a built-in module. Built-in modules are instantiated by
- // creating a new instance of a v8::ObjectTemplate rather than by executing
- // code. This function takes a ModuleTemplateGetter rather than a
- // v8::ObjectTemplate directly so that embedders can create object templates
- // lazily.
- void AddBuiltinModule(const std::string& id, ModuleTemplateGetter templ);
+ void AddBuiltinModule(const std::string& id, ModuleGetter getter);
protected:
void AttemptToLoadMoreModules(Runner* runner);
private:
- typedef std::map<std::string, ModuleTemplateGetter> BuiltinModuleMap;
+ typedef std::map<std::string, ModuleGetter> BuiltinModuleMap;
// From RunnerDelegate:
virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
new file mode 100644
index 0000000..ebe75bb
--- /dev/null
+++ b/gin/modules/timer.cc
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gin/modules/timer.h"
+
+#include "base/bind.h"
+#include "gin/object_template_builder.h"
+#include "gin/per_context_data.h"
+
+namespace gin {
+
+namespace {
+
+v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
+ return gin::StringToSymbol(isolate, "::gin::Timer");
+}
+
+} // namespace
+
+// Timer
+
+gin::WrapperInfo Timer::kWrapperInfo = { gin::kEmbedderNativeGin };
+
+// static
+Handle<Timer> Timer::Create(TimerType type, v8::Isolate* isolate, int delay_ms,
+ v8::Handle<v8::Function> function) {
+ return CreateHandle(isolate, new Timer(isolate, type == TYPE_REPEATING,
+ delay_ms, function));
+}
+
+ObjectTemplateBuilder Timer::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+ return Wrappable<Timer>::GetObjectTemplateBuilder(isolate)
+ .SetMethod("cancel",
+ base::Bind(&base::Timer::Stop, base::Unretained(&timer_)))
+ .SetMethod("reset",
+ base::Bind(&base::Timer::Reset, base::Unretained(&timer_)));
+}
+
+Timer::Timer(v8::Isolate* isolate, bool repeating, int delay_ms,
+ v8::Handle<v8::Function> function)
+ : weak_factory_(this),
+ timer_(false, repeating),
+ runner_(PerContextData::From(
+ isolate->GetCurrentContext())->runner()->GetWeakPtr()) {
+ GetWrapper(runner_->isolate())->SetHiddenValue(GetHiddenPropertyName(isolate),
+ function);
+ timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
+ base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr()));
+}
+
+Timer::~Timer() {
+}
+
+void Timer::OnTimerFired() {
+ if (!runner_)
+ return;
+ Runner::Scope scope(runner_.get());
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(
+ GetWrapper(runner_->isolate())->GetHiddenValue(
+ GetHiddenPropertyName(runner_->isolate())));
+ runner_->Call(function, v8::Undefined(runner_->isolate()), 0, NULL);
+}
+
+
+// TimerModule
+
+WrapperInfo TimerModule::kWrapperInfo = { kEmbedderNativeGin };
+
+// static
+Handle<TimerModule> TimerModule::Create(v8::Isolate* isolate) {
+ return CreateHandle(isolate, new TimerModule());
+}
+
+// static
+v8::Local<v8::Value> TimerModule::GetModule(v8::Isolate* isolate) {
+ return Create(isolate)->GetWrapper(isolate);
+}
+
+TimerModule::TimerModule() {
+}
+
+TimerModule::~TimerModule() {
+}
+
+ObjectTemplateBuilder TimerModule::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return Wrappable<TimerModule>::GetObjectTemplateBuilder(isolate)
+ .SetMethod("createOneShot",
+ base::Bind(&Timer::Create, Timer::TYPE_ONE_SHOT))
+ .SetMethod("createRepeating",
+ base::Bind(&Timer::Create, Timer::TYPE_REPEATING));
+}
+
+} // namespace gin
diff --git a/gin/modules/timer.h b/gin/modules/timer.h
new file mode 100644
index 0000000..c39e131
--- /dev/null
+++ b/gin/modules/timer.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GIN_MODULES_TIMER_H_
+#define GIN_MODULES_TIMER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "gin/gin_export.h"
+#include "gin/handle.h"
+#include "gin/runner.h"
+#include "gin/wrappable.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+class ObjectTemplateBuilder;
+
+// A simple scriptable timer that can work in one-shot or repeating mode.
+class GIN_EXPORT Timer : public Wrappable<Timer> {
+ public:
+ enum TimerType {
+ TYPE_ONE_SHOT,
+ TYPE_REPEATING
+ };
+
+ static WrapperInfo kWrapperInfo;
+ static Handle<Timer> Create(TimerType type, v8::Isolate* isolate,
+ int delay_ms, v8::Handle<v8::Function> function);
+
+ virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE;
+
+ private:
+ Timer(v8::Isolate* isolate, bool repeating, int delay_ms,
+ v8::Handle<v8::Function> function);
+ virtual ~Timer();
+ void OnTimerFired();
+
+ base::WeakPtrFactory<Timer> weak_factory_;
+ base::Timer timer_;
+ base::WeakPtr<gin::Runner> runner_;
+};
+
+
+class GIN_EXPORT TimerModule : public Wrappable<TimerModule> {
+ public:
+ static WrapperInfo kWrapperInfo;
+ static Handle<TimerModule> Create(v8::Isolate* isolate);
+ static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
+
+ private:
+ TimerModule();
+ virtual ~TimerModule();
+
+ virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE;
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_TIMER_H_
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
new file mode 100644
index 0000000..96972d5
--- /dev/null
+++ b/gin/modules/timer_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gin/modules/timer.h"
+
+#include "base/message_loop/message_loop.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/public/isolate_holder.h"
+#include "gin/runner.h"
+#include "gin/test/v8_test.h"
+#include "gin/try_catch.h"
+#include "gin/wrappable.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+namespace {
+
+class Result : public Wrappable<Result> {
+ public:
+ static WrapperInfo kWrapperInfo;
+ static Handle<Result> Create(v8::Isolate* isolate) {
+ return CreateHandle(isolate, new Result());
+ }
+
+ int count() const { return count_; }
+ void set_count(int count) { count_ = count; }
+
+ void quit() {
+ base::MessageLoop::current()->Quit();
+ }
+
+ private:
+ Result() : count_(0) {
+ }
+
+ virtual ~Result() {
+ }
+
+ virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE {
+ return Wrappable<Result>::GetObjectTemplateBuilder(isolate)
+ .SetProperty("count", &Result::count, &Result::set_count)
+ .SetMethod("quit", &Result::quit);
+ }
+
+ int count_;
+};
+
+WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
+
+} // namespace
+
+typedef V8Test TimerUnittest;
+
+TEST_F(TimerUnittest, OneShot) {
+ v8::Isolate* isolate = instance_->isolate();
+
+ RunnerDelegate delegate;
+ Runner runner(&delegate, isolate);
+ Runner::Scope scope(&runner);
+
+ Handle<TimerModule> timer_module = TimerModule::Create(isolate);
+ Handle<Result> result = Result::Create(isolate);
+
+ EXPECT_FALSE(runner.global().IsEmpty());
+ runner.global()->Set(StringToV8(isolate, "timer"),
+ timer_module->GetWrapper(isolate));
+ runner.global()->Set(StringToV8(isolate, "result"),
+ result->GetWrapper(isolate));
+
+ std::string source =
+ "timer.createOneShot(100, function() {"
+ " result.count++;"
+ " result.quit();"
+ "});";
+
+ base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
+ runner.Run(source, "script");
+ EXPECT_EQ(0, result->count());
+
+ loop.Run();
+ loop.RunUntilIdle();
+
+ EXPECT_EQ(1, result->count());
+}
+
+TEST_F(TimerUnittest, Repeating) {
+ v8::Isolate* isolate = instance_->isolate();
+
+ RunnerDelegate delegate;
+ Runner runner(&delegate, isolate);
+ Runner::Scope scope(&runner);
+
+ Handle<TimerModule> timer_module = TimerModule::Create(isolate);
+ Handle<Result> result = Result::Create(isolate);
+
+ EXPECT_FALSE(runner.global().IsEmpty());
+ runner.global()->Set(StringToV8(isolate, "timer"),
+ timer_module->GetWrapper(isolate));
+ runner.global()->Set(StringToV8(isolate, "result"),
+ result->GetWrapper(isolate));
+
+ // TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create
+ // test case and report.
+ std::string source =
+ "timer.createRepeating(10, function() {"
+ " result.count++;"
+ " if (result.count == 3) {"
+ " result.quit();"
+ " }"
+ "});";
+
+ base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
+ runner.Run(source, "script");
+ EXPECT_EQ(0, result->count());
+
+ loop.Run();
+ EXPECT_EQ(3, result->count());
+}
+
+} // namespace gin