Skip to content

Commit 263e33a

Browse files
committed
Revert "Get rid of the old timer binding"
This reverts commit cc82724. Conflicts: src/node.cc wscript
1 parent 23b8931 commit 263e33a

4 files changed

Lines changed: 271 additions & 0 deletions

File tree

src/node.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#ifdef __POSIX__
6464
# include <node_signal_watcher.h>
6565
# include <node_stat_watcher.h>
66+
# include <node_timer.h>
6667
#endif
6768
#include <node_child_process.h>
6869
#include <node_constants.h>
@@ -1888,6 +1889,11 @@ static Handle<Value> Binding(const Arguments& args) {
18881889
binding_cache->Set(module, exports);
18891890
#endif
18901891

1892+
} else if (!strcmp(*module_v, "timer")) {
1893+
exports = Object::New();
1894+
Timer::Initialize(exports);
1895+
binding_cache->Set(module, exports);
1896+
18911897
} else if (!strcmp(*module_v, "natives")) {
18921898
exports = Object::New();
18931899
DefineJavaScript(exports);

src/node_timer.cc

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
#include <node.h>
23+
#include <node_timer.h>
24+
#include <assert.h>
25+
26+
namespace node {
27+
28+
using namespace v8;
29+
30+
Persistent<FunctionTemplate> Timer::constructor_template;
31+
32+
33+
static Persistent<String> timeout_symbol;
34+
static Persistent<String> repeat_symbol;
35+
static Persistent<String> callback_symbol;
36+
37+
38+
void Timer::Initialize(Handle<Object> target) {
39+
HandleScope scope;
40+
41+
Local<FunctionTemplate> t = FunctionTemplate::New(Timer::New);
42+
constructor_template = Persistent<FunctionTemplate>::New(t);
43+
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
44+
constructor_template->SetClassName(String::NewSymbol("Timer"));
45+
46+
timeout_symbol = NODE_PSYMBOL("timeout");
47+
repeat_symbol = NODE_PSYMBOL("repeat");
48+
callback_symbol = NODE_PSYMBOL("callback");
49+
50+
NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", Timer::Start);
51+
NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", Timer::Stop);
52+
NODE_SET_PROTOTYPE_METHOD(constructor_template, "again", Timer::Again);
53+
54+
constructor_template->InstanceTemplate()->SetAccessor(repeat_symbol,
55+
RepeatGetter, RepeatSetter);
56+
57+
target->Set(String::NewSymbol("Timer"), constructor_template->GetFunction());
58+
}
59+
60+
61+
Handle<Value> Timer::RepeatGetter(Local<String> property,
62+
const AccessorInfo& info) {
63+
HandleScope scope;
64+
Timer *timer = ObjectWrap::Unwrap<Timer>(info.This());
65+
66+
assert(timer);
67+
assert(property == repeat_symbol);
68+
69+
Local<Integer> v = Integer::New(timer->watcher_.repeat);
70+
71+
return scope.Close(v);
72+
}
73+
74+
void Timer::RepeatSetter(Local<String> property,
75+
Local<Value> value,
76+
const AccessorInfo& info) {
77+
HandleScope scope;
78+
Timer *timer = ObjectWrap::Unwrap<Timer>(info.This());
79+
80+
assert(timer);
81+
assert(property == repeat_symbol);
82+
83+
timer->watcher_.repeat = NODE_V8_UNIXTIME(value);
84+
}
85+
86+
void Timer::OnTimeout(EV_P_ ev_timer *watcher, int revents) {
87+
Timer *timer = static_cast<Timer*>(watcher->data);
88+
89+
assert(revents == EV_TIMEOUT);
90+
91+
HandleScope scope;
92+
93+
Local<Value> callback_v = timer->handle_->Get(callback_symbol);
94+
if (!callback_v->IsFunction()) {
95+
timer->Stop();
96+
return;
97+
}
98+
99+
Local<Function> callback = Local<Function>::Cast(callback_v);
100+
101+
TryCatch try_catch;
102+
103+
callback->Call(timer->handle_, 0, NULL);
104+
105+
if (try_catch.HasCaught()) {
106+
FatalException(try_catch);
107+
}
108+
109+
if (timer->watcher_.repeat == 0) timer->Unref();
110+
}
111+
112+
113+
Timer::~Timer() {
114+
ev_timer_stop(EV_DEFAULT_UC_ &watcher_);
115+
}
116+
117+
118+
Handle<Value> Timer::New(const Arguments& args) {
119+
if (!args.IsConstructCall()) {
120+
return FromConstructorTemplate(constructor_template, args);
121+
}
122+
123+
HandleScope scope;
124+
125+
Timer *t = new Timer();
126+
t->Wrap(args.Holder());
127+
128+
return args.This();
129+
}
130+
131+
Handle<Value> Timer::Start(const Arguments& args) {
132+
HandleScope scope;
133+
Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder());
134+
135+
if (args.Length() != 2)
136+
return ThrowException(String::New("Bad arguments"));
137+
138+
bool was_active = ev_is_active(&timer->watcher_);
139+
140+
ev_tstamp after = NODE_V8_UNIXTIME(args[0]);
141+
ev_tstamp repeat = NODE_V8_UNIXTIME(args[1]);
142+
ev_timer_init(&timer->watcher_, Timer::OnTimeout, after, repeat);
143+
timer->watcher_.data = timer;
144+
145+
// Update the event loop time. Need to call this because processing JS can
146+
// take non-negligible amounts of time.
147+
ev_now_update(EV_DEFAULT_UC);
148+
149+
ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_);
150+
151+
if (!was_active) timer->Ref();
152+
153+
return Undefined();
154+
}
155+
156+
157+
Handle<Value> Timer::Stop(const Arguments& args) {
158+
HandleScope scope;
159+
Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder());
160+
timer->Stop();
161+
return Undefined();
162+
}
163+
164+
165+
void Timer::Stop() {
166+
if (watcher_.active) {
167+
ev_timer_stop(EV_DEFAULT_UC_ &watcher_);
168+
Unref();
169+
}
170+
}
171+
172+
173+
Handle<Value> Timer::Again(const Arguments& args) {
174+
HandleScope scope;
175+
Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder());
176+
177+
int was_active = ev_is_active(&timer->watcher_);
178+
179+
if (args.Length() > 0) {
180+
ev_tstamp repeat = NODE_V8_UNIXTIME(args[0]);
181+
if (repeat > 0) timer->watcher_.repeat = repeat;
182+
}
183+
184+
ev_timer_again(EV_DEFAULT_UC_ &timer->watcher_);
185+
186+
// ev_timer_again can start or stop the watcher.
187+
// So we need to check what happened and adjust the ref count
188+
// appropriately.
189+
190+
if (ev_is_active(&timer->watcher_)) {
191+
if (!was_active) timer->Ref();
192+
} else {
193+
if (was_active) timer->Unref();
194+
}
195+
196+
return Undefined();
197+
}
198+
199+
200+
} // namespace node

src/node_timer.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
#ifndef SRC_NODE_TIMER_H_
23+
#define SRC_NODE_TIMER_H_
24+
25+
#include <node.h>
26+
#include <node_object_wrap.h>
27+
#include <v8.h>
28+
#include <ev.h>
29+
30+
namespace node {
31+
32+
class Timer : ObjectWrap {
33+
public:
34+
static void Initialize(v8::Handle<v8::Object> target);
35+
36+
protected:
37+
static v8::Persistent<v8::FunctionTemplate> constructor_template;
38+
39+
Timer() : ObjectWrap() {
40+
// dummy timeout values
41+
ev_timer_init(&watcher_, OnTimeout, 0., 1.);
42+
watcher_.data = this;
43+
}
44+
45+
~Timer();
46+
47+
static v8::Handle<v8::Value> New(const v8::Arguments& args);
48+
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
49+
static v8::Handle<v8::Value> Stop(const v8::Arguments& args);
50+
static v8::Handle<v8::Value> Again(const v8::Arguments& args);
51+
static v8::Handle<v8::Value> RepeatGetter(v8::Local<v8::String> property,
52+
const v8::AccessorInfo& info);
53+
static void RepeatSetter(v8::Local<v8::String> property,
54+
v8::Local<v8::Value> value,
55+
const v8::AccessorInfo& info);
56+
57+
private:
58+
static void OnTimeout(EV_P_ ev_timer *watcher, int revents);
59+
void Stop();
60+
ev_timer watcher_;
61+
};
62+
63+
} // namespace node
64+
#endif // SRC_NODE_TIMER_H_

wscript

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ def build(bld):
838838
node.source += " src/node_io_watcher.cc "
839839
node.source += " src/node_stdio.cc "
840840
node.source += " src/node_child_process.cc "
841+
node.source += " src/node_timer.cc "
841842

842843
node.source += bld.env["PLATFORM_FILE"]
843844
if not product_type_is_lib:

0 commit comments

Comments
 (0)