func Define(vm *otto.Otto, l *loop.Loop) error { if v, err := vm.Get("setTimeout"); err != nil { return err } else if !v.IsUndefined() { return nil } newTimer := func(interval bool) func(call otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { delay, _ := call.Argument(1).ToInteger() if delay < minDelay[interval] { delay = minDelay[interval] } t := &timerTask{ duration: time.Duration(delay) * time.Millisecond, call: call, interval: interval, } l.Add(t) t.timer = time.AfterFunc(t.duration, func() { l.Ready(t) }) value, err := call.Otto.ToValue(t) if err != nil { panic(err) } return value } } vm.Set("setTimeout", newTimer(false)) vm.Set("setInterval", newTimer(true)) vm.Set("setImmediate", func(call otto.FunctionCall) otto.Value { t := &timerTask{ duration: time.Millisecond, call: call, } l.Add(t) t.timer = time.AfterFunc(t.duration, func() { l.Ready(t) }) value, err := call.Otto.ToValue(t) if err != nil { panic(err) } return value }) clearTimeout := func(call otto.FunctionCall) otto.Value { v, _ := call.Argument(0).Export() if t, ok := v.(*timerTask); ok { t.stopped = true t.timer.Stop() l.Remove(t) } return otto.UndefinedValue() } vm.Set("clearTimeout", clearTimeout) vm.Set("clearInterval", clearTimeout) vm.Set("clearImmediate", clearTimeout) return nil }