Skip to content

Commit

Permalink
Adds setInterval, clearInterval, clearTimeout.
Browse files Browse the repository at this point in the history
  • Loading branch information
qti3e authored and ry committed May 23, 2018
1 parent 3171ba4 commit cb222ce
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 19 deletions.
7 changes: 5 additions & 2 deletions globals.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setTimeout } from "./timers";
import * as timer from "./timers";

// If you use the eval function indirectly, by invoking it via a reference
// other than eval, as of ECMAScript 5 it works in the global scope rather than
Expand All @@ -14,7 +14,10 @@ export const _global = globalEval("this");
_global["window"] = _global; // Create a window object.
import "./url";

_global["setTimeout"] = setTimeout;
_global["setTimeout"] = timer.setTimeout;
_global["setInterval"] = timer.setInterval;
_global["clearTimeout"] = timer.clearTimer;
_global["clearInterval"] = timer.clearTimer;

const print = V8Worker2.print;

Expand Down
3 changes: 3 additions & 0 deletions msg.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ message Msg {
ExitMsg exit = 14;
TimerStartMsg timer_start = 15;
TimerReadyMsg timer_ready = 16;
TimerClearMsg timer_clear = 17;
}
}

Expand Down Expand Up @@ -60,3 +61,5 @@ message TimerReadyMsg {
optional int32 id = 1;
optional bool done = 2;
}

message TimerClearMsg { optional int32 id = 1; }
6 changes: 6 additions & 0 deletions testdata/004_set_timeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ setTimeout(function() {
}, 10);

console.log("Hello");

const id = setTimeout(function() {
console.log("Not printed");
}, 10000);

clearTimeout(id);
7 changes: 7 additions & 0 deletions testdata/010_set_interval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const id = setInterval(function() {
console.log("test")
}, 200);

setTimeout(function() {
clearInterval(id)
}, 500)
2 changes: 2 additions & 0 deletions testdata/010_set_interval.ts.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test
test
72 changes: 58 additions & 14 deletions timers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,79 @@ import (
"time"
)

type Timer struct {
Id int32
Done bool
Cleared bool
Interval bool
Duration int32 // In milliseconds
}

var timers = make(map[int32]*Timer)

func InitTimers() {
Sub("timers", func(buf []byte) []byte {
msg := &Msg{}
check(proto.Unmarshal(buf, msg))
switch msg.Payload.(type) {
case *Msg_TimerStart:
payload := msg.GetTimerStart()
return HandleTimerStart(*payload.Id, *payload.Interval,
*payload.Duration)
timers[*payload.Id] = &Timer{
Id: *payload.Id,
Done: false,
Interval: *payload.Interval,
Duration: *payload.Duration,
Cleared: false,
}
timers[*payload.Id].StartTimer()
return nil
case *Msg_TimerClear:
payload := msg.GetTimerClear()
// TODO maybe need mutex here.
timer := timers[*payload.Id]
timer.Clear()
return nil
default:
panic("[timers] Unexpected message " + string(buf))
}
})
}

func HandleTimerStart(id int32, interval bool, duration int32) []byte {
func (t *Timer) Clear() {
if !t.Cleared {
wg.Done()
t.Cleared = true
delete(timers, t.Id)
}
t.Done = true
}

func (t *Timer) StartTimer() {
wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(time.Duration(duration) * time.Millisecond)
payload, err := proto.Marshal(&Msg{
Payload: &Msg_TimerReady{
TimerReady: &TimerReadyMsg{
Id: &id,
defer t.Clear()
for {
time.Sleep(time.Duration(t.Duration) * time.Millisecond)
if !t.Interval {
t.Done = true
}
pubMsg(&Msg{
Payload: &Msg_TimerReady{
TimerReady: &TimerReadyMsg{
Id: &t.Id,
Done: &t.Done,
},
},
},
})
check(err)
Pub("timers", payload)
})
if t.Done {
return
}
}
}()
return nil
}

func pubMsg(msg *Msg) {
payload, err := proto.Marshal(msg)
check(err)
Pub("timers", payload)
}
48 changes: 45 additions & 3 deletions timers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import * as dispatch from "./dispatch";
let nextTimerId = 1;

// tslint:disable-next-line:no-any
type TimerCallback = (...args: any[]) => void;
export type TimerCallback = (...args: any[]) => void;

interface Timer {
id: number;
cb: TimerCallback;
interval: boolean;
// tslint:disable-next-line:no-any
args: any[];
duration: number; // milliseconds
}

Expand All @@ -23,17 +25,26 @@ function onMessage(payload: Uint8Array) {
const msg = pb.Msg.decode(payload);
const { id, done } = msg.timerReady;
const timer = timers.get(id);
timer.cb();
if (!timer) {
return;
}
timer.cb(...timer.args);
if (done) {
timers.delete(id);
}
}

export function setTimeout(cb: TimerCallback, duration: number): number {
export function setTimeout(
cb: TimerCallback,
duration: number,
// tslint:disable-next-line:no-any
...args: any[]
): number {
const timer = {
id: nextTimerId++,
interval: false,
duration,
args,
cb
};
timers.set(timer.id, timer);
Expand All @@ -46,3 +57,34 @@ export function setTimeout(cb: TimerCallback, duration: number): number {
});
return timer.id;
}

// TODO DRY with setTimeout
export function setInterval(
cb: TimerCallback,
repeat: number,
// tslint:disable-next-line:no-any
...args: any[]
): number {
const timer = {
id: nextTimerId++,
interval: true,
duration: repeat,
args,
cb
};
timers.set(timer.id, timer);
dispatch.sendMsg("timers", {
timerStart: {
id: timer.id,
interval: true,
duration: repeat
}
});
return timer.id;
}

export function clearTimer(id: number) {
dispatch.sendMsg("timers", {
timerClear: { id }
});
}

0 comments on commit cb222ce

Please sign in to comment.