summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--main.go49
-rw-r--r--main.ts4
-rw-r--r--msg.proto13
-rw-r--r--os.ts2
-rw-r--r--testdata/004_set_timeout.ts5
-rw-r--r--testdata/004_set_timeout.ts.out2
-rw-r--r--timers.ts43
8 files changed, 117 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index a7ee97eca..27ce567d2 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ TS_FILES = \
msg.pb.js \
os.ts \
runtime.ts \
+ timers.ts \
util.ts
deno: assets.go msg.pb.go main.go
diff --git a/main.go b/main.go
index be7ad541f..39ba9cb87 100644
--- a/main.go
+++ b/main.go
@@ -9,8 +9,13 @@ import (
"os"
"path"
"runtime"
+ "sync"
+ "time"
)
+var wg sync.WaitGroup
+var resChan chan *Msg
+
func SourceCodeHash(filename string, sourceCodeBuf []byte) string {
h := md5.New()
h.Write([]byte(filename))
@@ -70,6 +75,22 @@ func HandleSourceCodeCache(filename string, sourceCode string,
return out
}
+func HandleTimerStart(id int32, interval bool, duration int32) []byte {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ time.Sleep(time.Duration(duration) * time.Millisecond)
+ resChan <- &Msg{
+ Payload: &Msg_TimerReady{
+ TimerReady: &TimerReadyMsg{
+ Id: id,
+ },
+ },
+ }
+ }()
+ return nil
+}
+
func UserHomeDir() string {
if runtime.GOOS == "windows" {
home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
@@ -121,7 +142,11 @@ func recv(buf []byte) []byte {
return HandleSourceCodeFetch(payload.Filename)
case *Msg_SourceCodeCache:
payload := msg.GetSourceCodeCache()
- return HandleSourceCodeCache(payload.Filename, payload.SourceCode, payload.OutputCode)
+ return HandleSourceCodeCache(payload.Filename, payload.SourceCode,
+ payload.OutputCode)
+ case *Msg_TimerStart:
+ payload := msg.GetTimerStart()
+ return HandleTimerStart(payload.Id, payload.Interval, payload.Duration)
default:
panic("Unexpected message")
}
@@ -137,6 +162,9 @@ func main() {
cwd, err := os.Getwd()
check(err)
+ resChan = make(chan *Msg)
+ doneChan := make(chan bool)
+
out, err := proto.Marshal(&Msg{
Payload: &Msg_Start{
Start: &StartMsg{
@@ -151,4 +179,23 @@ func main() {
os.Stderr.WriteString(err.Error())
os.Exit(1)
}
+
+ // In a goroutine, we wait on for all goroutines to complete (for example
+ // timers). We use this to signal to the main thread to exit.
+ go func() {
+ wg.Wait()
+ doneChan <- true
+ }()
+
+ for {
+ select {
+ case msg := <-resChan:
+ out, err := proto.Marshal(msg)
+ err = worker.SendBytes(out)
+ check(err)
+ case <-doneChan:
+ // All goroutines have completed. Now we can exit main().
+ return
+ }
+ }
}
diff --git a/main.ts b/main.ts
index e840e5b5a..d853cc2b1 100644
--- a/main.ts
+++ b/main.ts
@@ -1,6 +1,7 @@
import { main as pb } from "./msg.pb";
import "./util";
import * as runtime from "./runtime";
+import * as timers from "./timers";
import * as path from "path";
function start(cwd: string, argv: string[]): void {
@@ -17,6 +18,9 @@ V8Worker2.recv((ab: ArrayBuffer) => {
case "start":
start(msg.start.cwd, msg.start.argv);
break;
+ case "timerReady":
+ timers.timerReady(msg.timerReady.id, msg.timerReady.done);
+ break;
default:
console.log("Unknown message", msg);
break;
diff --git a/msg.proto b/msg.proto
index 181dcc551..1ab78b690 100644
--- a/msg.proto
+++ b/msg.proto
@@ -10,6 +10,8 @@ message Msg {
SourceCodeFetchResMsg source_code_fetch_res = 12;
SourceCodeCacheMsg source_code_cache = 13;
ExitMsg exit = 14;
+ TimerStartMsg timer_start = 15;
+ TimerReadyMsg timer_ready = 16;
}
}
@@ -33,3 +35,14 @@ message SourceCodeCacheMsg {
}
message ExitMsg { int32 code = 1; }
+
+message TimerStartMsg {
+ int32 id = 1;
+ bool interval = 2;
+ int32 duration = 3; // In milliseconds.
+}
+
+message TimerReadyMsg {
+ int32 id = 1;
+ bool done = 2;
+}
diff --git a/os.ts b/os.ts
index d09026c6c..44c3ab508 100644
--- a/os.ts
+++ b/os.ts
@@ -35,7 +35,7 @@ function typedArrayToArrayBuffer(ta: TypedArray): ArrayBuffer {
return ab as ArrayBuffer;
}
-function sendMsgFromObject(obj: pb.IMsg): null | pb.Msg {
+export function sendMsgFromObject(obj: pb.IMsg): null | pb.Msg {
const msg = pb.Msg.fromObject(obj);
const ui8 = pb.Msg.encode(msg).finish();
const ab = typedArrayToArrayBuffer(ui8);
diff --git a/testdata/004_set_timeout.ts b/testdata/004_set_timeout.ts
new file mode 100644
index 000000000..fe55e31ba
--- /dev/null
+++ b/testdata/004_set_timeout.ts
@@ -0,0 +1,5 @@
+setTimeout(function() {
+ console.log("World");
+}, 10);
+
+console.log("Hello");
diff --git a/testdata/004_set_timeout.ts.out b/testdata/004_set_timeout.ts.out
new file mode 100644
index 000000000..f9264f7fb
--- /dev/null
+++ b/testdata/004_set_timeout.ts.out
@@ -0,0 +1,2 @@
+Hello
+World
diff --git a/timers.ts b/timers.ts
new file mode 100644
index 000000000..ed84c00e9
--- /dev/null
+++ b/timers.ts
@@ -0,0 +1,43 @@
+import { _global } from "./util";
+import { sendMsgFromObject } from "./os";
+
+let nextTimerId = 1;
+
+// tslint:disable-next-line:no-any
+type TimerCallback = (...args: any[]) => void;
+
+interface Timer {
+ id: number;
+ cb: TimerCallback;
+ interval: boolean;
+ duration: number; // milliseconds
+}
+
+const timers = new Map<number, Timer>();
+
+export function setTimeout(cb: TimerCallback, duration: number): number {
+ const timer = {
+ id: nextTimerId++,
+ interval: false,
+ duration,
+ cb
+ };
+ timers.set(timer.id, timer);
+ sendMsgFromObject({
+ timerStart: {
+ id: timer.id,
+ interval: false,
+ duration
+ }
+ });
+ return timer.id;
+}
+_global["setTimeout"] = setTimeout;
+
+export function timerReady(id: number, done: boolean): void {
+ const timer = timers.get(id);
+ timer.cb();
+ if (done) {
+ timers.delete(id);
+ }
+}