// Bind binds the method to the specified runtime. func (m *Method) Bind(runtime *otto.Otto) error { castFunc := (func(call otto.FunctionCall) otto.Value)(m.Func) if err := runtime.Set("$$"+m.Name, castFunc); err != nil { return err } return nil }
func (ctrl *JsController) addDiscoveryService(o *otto.Otto) { o.Set("discover", func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) == 0 { glog.Errorf("DISCOVER: Missing arguments") return otto.NullValue() } url, _ := call.Argument(0).ToString() upstreams, err := ctrl.DiscoveryService.Get(url) if err != nil { glog.Errorf("Failed to discover upstreams: %v", err) return otto.NullValue() } glog.Infof("Discovered upstreams: %v", upstreams) result, err := o.ToValue(upstreams) if err != nil { glog.Errorf("Failed to convert: %v", err) return otto.NullValue() } return result }) }
// NewWriter adds a write method to the specified runtime that allows // client code to write to the specified io.Writer. // // The client function created has the following syntax: // // var response = writeMethodName(contentToWrite) // // Response object: // // { // len: bytes_written, // error: error|undefined // } func NewWriter(runtime *otto.Otto, methodName string, writer io.Writer) error { runtime.Set(methodName, func(call otto.FunctionCall) otto.Value { var data string var count int var err error var val otto.Value if data, err = call.Argument(0).ToString(); err == nil { if count, err = writer.Write([]byte(data)); err == nil { if val, err = makeMap(runtime, map[string]interface{}{"len": count}); err != nil { raiseError(runtime, "Failed to create output object: %s", err) } else { return val } } } if err != nil { if val, err := makeMap(runtime, map[string]interface{}{"len": 0, "error": err.Error()}); err != nil { raiseError(runtime, "Failed to create output object: %s", err) return otto.UndefinedValue() } else { return val } } return otto.UndefinedValue() }) return nil }
func (b Buffers) Sync(o *otto.Otto) error { if v, err := o.ToValue(b); err != nil { return err } else { o.Set("buffers", v) } return nil }
func (ctrl *JsController) addLoggers(o *otto.Otto) { o.Set("info", func(call otto.FunctionCall) otto.Value { return log("info", call) }) o.Set("error", func(call otto.FunctionCall) otto.Value { return log("error", call) }) }
func InitEnv(vm *otto.Otto) { vm.Set("G", new(Env)) vm.Set("toJS", func(call otto.FunctionCall) otto.Value { result, err := vm.ToValue(call.Argument(0)) if err != nil { panic(err) } return result }) }
// RegisterMethodFileOpen registers a method that is capable of opening files. // // Response object: // // { // ok: true|false, // reader: "readFile" // the method to use to read from the file // } // // To read the entire file into a variable: // // // in Go... // RegisterMethodFileOpen(js, "openFile") // // // in the script... // var file = openFile("filename"); // open the file // var read = eval(file.reader); // get the reader method // var close = eval(file.closer); // get the closer method // // var fileContents = read(-1); // read everything // close(); // close the file // func RegisterMethodFileOpen(runtime *otto.Otto, methodName string) error { runtime.Set(methodName, func(call otto.FunctionCall) otto.Value { // check the arguments if len(call.ArgumentList) != 1 { raiseError(runtime, "%s takes 1 arguments: %s(filename)", methodName, methodName) return otto.UndefinedValue() } // get the arguments var filename string var err error if filename, err = call.Argument(0).ToString(); err != nil { raiseError(runtime, "%s first argument must be a string containing the filename", methodName) return otto.UndefinedValue() } // open the file var file io.ReadCloser if file, err = os.Open(filename); err != nil { raiseError(runtime, "Failed to open file '%s': %s", filename, err) return otto.UndefinedValue() } // add the reader var readerMethodName string = generateMethodName("fileRead") NewReader(runtime, readerMethodName, file) // add the closer var closerMethodName string = generateMethodName("fileClose") runtime.Set(closerMethodName, func(call otto.FunctionCall) otto.Value { if err := file.Close(); err != nil { raiseError(runtime, "Failed to close file '%s': %s", filename, err) return otto.FalseValue() } return otto.TrueValue() }) var response otto.Value if response, err = makeMap(runtime, map[string]interface{}{"reader": readerMethodName, "closer": closerMethodName, "ok": true}); err != nil { raiseError(runtime, "%s failed to make response map.", methodName) return otto.UndefinedValue() } // done return response }) return nil }
func SetOttoVM(vm *otto.Otto, pmap map[string]string, key string, ptype string) { if value, ok := pmap[key]; ok { switch ptype { case "string": vm.Set(key, value) case "int": intval, err := strconv.Atoi(value) if err != nil { log.Println(err.Error()) } else { vm.Set(key, intval) } } } }
// SetOnce sets a name or value only if it doesn't exist. // // Returns whether the value was set or not, or an error if it failed to // set it. // // For acceptable values, see http://godoc.org/github.com/robertkrimen/otto#Otto.Set func SetOnce(runtime *otto.Otto, name string, value interface{}) (bool, error) { if !Exist(runtime, name) { if err := runtime.Set(name, value); err != nil { return false, err } return true, nil } // nothing to do return false, nil }
func setValueAtPath(context *otto.Otto, path string, value interface{}) { parts := strings.Split(path, ".") parentCount := len(parts) - 1 if parentCount > 0 { parentPath := strings.Join(parts[0:parentCount], ".") parent, err := context.Object("(" + parentPath + ")") if err != nil { emptyObject, _ := context.Object(`({})`) setValueAtPath(context, parentPath, emptyObject) } parent, _ = context.Object("(" + parentPath + ")") parent.Set(parts[parentCount], value) } else { context.Set(path, value) } }
func Define(vm *otto.Otto, argv []string) error { if v, err := vm.Get("process"); err != nil { return err } else if !v.IsUndefined() { return nil } env := make(map[string]string) for _, e := range os.Environ() { a := strings.SplitN(e, "=", 2) env[a[0]] = a[1] } return vm.Set("process", map[string]interface{}{ "env": env, "argv": argv, }) }
func createContext(vm *otto.Otto, event chan otto.Value) otto.Value { var cbfunc = func(invar ...interface{}) { var lovar otto.Value if len(invar) > 0 { lovar, _ = vm.ToValue(invar[0]) } else { lovar = otto.NullValue() } event <- lovar close(event) } vm.Set("_iopipe_cb", cbfunc) vm.Run(`_iopipe_context = { "done": _iopipe_cb, "success": _iopipe_cb, "fail": _iopipe_cb }`) jscontext, _ := vm.Get("_iopipe_context") return jscontext }
// InitializeRuntime initializes a runtime, setting classes avaible in scripting etc // This returns the first runtime error func (api *API) InitializeRuntime(runtime *otto.Otto, object *Object) error { var engErr, objErr, inErr error engErr = runtime.Set("engine", NewEngineInterface(api.base)) objErr = runtime.Set("object", NewObjectInterface(object)) inErr = runtime.Set("input", NewInputInterface(api.base.Input())) return checkAnyError(engErr, objErr, inErr) }
func loadDefaults(runtime *otto.Otto) error { if err := runtime.Set("defaultTTL", ttl); err != nil { return err } if err := runtime.Set("defaultEnvironment", environment); err != nil { return err } if err := runtime.Set("cleanImageName", func(call otto.FunctionCall) otto.Value { name := call.Argument(0).String() result, _ := otto.ToValue(utils.CleanImageName(name)) return result }); err != nil { return err } if err := runtime.Set("removeSlash", func(call otto.FunctionCall) otto.Value { name := call.Argument(0).String() result, _ := otto.ToValue(utils.RemoveSlash(name)) return result }); err != nil { return err } return nil }
// NewReader adds a read method to the specified runtime that allows // client code to read from the specified reader. // // The client function created has the following syntax: // // var response = readMethodName(bytesToRead); // // Response object: // // { // data: "This was read from the reader.", // eof: false|true, // error: error|undefined // } // // If eof is false, client code should keep calling the read method // until all data has been read. // // For example, to stream from the Stdin pipe: // // // in go... // NewReader(js, "readStdIn", os.Stdin) // // // in a script... // var data = ""; // var response = {"eof":false}; // while (!response.eof) { // response = readStdIn(255); // data += response.data; // } // // Passing -1 as the bytesToRead will read the entire contents from // the reader immediately. func NewReader(runtime *otto.Otto, methodName string, reader io.Reader) error { runtime.Set(methodName, func(call otto.FunctionCall) otto.Value { var err error var l int64 var all []byte var val otto.Value var bytesRead int if l, err = call.Argument(0).ToInteger(); err != nil { raiseError(runtime, "First argument to read methods must be an integer: %s", err) } else { if l == -1 { all, err = ioutil.ReadAll(reader) if err != nil { raiseError(runtime, "Failed to read from io.Reader: %s", err) } else { if val, err = makeMap(runtime, map[string]interface{}{"data": string(all), "eof": true}); err != nil { raiseError(runtime, "Failed to create output object: %s", err) } else { return val } } } else { // read x bytes from the reader buf := make([]byte, l) bytesRead, err = reader.Read(buf) var isEof bool = false if err == io.EOF { isEof = true } else if err != nil { raiseError(runtime, "Failed to read from io.Reader: %s", err) } // get the data var dataStr string if bytesRead > 0 { dataStr = string(buf) } if val, err = makeMap(runtime, map[string]interface{}{"data": dataStr, "eof": isEof}); err != nil { raiseError(runtime, "Failed to create output object: %s", err) } else { return val } } } if err != nil { if val, err := makeMap(runtime, map[string]interface{}{"eof": true, "error": err.Error()}); err != nil { raiseError(runtime, "Failed to create output object: %s", err) return otto.UndefinedValue() } else { return val } } // nothing to return return otto.UndefinedValue() }) return nil }
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 }
func injectRuntime(vm *otto.Otto) { var err error err = vm.Set("sqrt", func(call otto.FunctionCall) otto.Value { f, err := call.Argument(0).ToFloat() if err != nil { panic(err) } r, err := otto.ToValue(math.Sqrt(f)) if err != nil { panic(err) } return r }) _, err = vm.Run(` gnr = { lerp: function(minIn, maxIn, minOut, maxOut) { return function(d) { return (d - minIn)/(maxIn - minIn)*(maxOut - minOut) + minOut; } }, lerpCap: function(minIn, maxIn, minOut, maxOut) { var f = gnr.lerp(minIn, maxIn, minOut, maxOut); return function(d) { if(d < minIn) { d = minIn; } if(d > maxIn) { d = maxIn; } return f(d); } }, vlerp: function(minIn, maxIn, minOut, maxOut) { var xLerp = gnr.lerp(minIn, maxIn, minOut.X, maxOut.X); var yLerp = gnr.lerp(minIn, maxIn, minOut.Y, maxOut.Y); var zLerp = gnr.lerp(minIn, maxIn, minOut.Z, maxOut.Z); return function(d) { return { X: xLerp(d), Y: yLerp(d), Z: zLerp(d) }; }; }, vlerpCap: function(minIn, maxIn, minOut, maxOut) { var xLerp = gnr.lerpCap(minIn, maxIn, minOut.X, maxOut.X); var yLerp = gnr.lerpCap(minIn, maxIn, minOut.Y, maxOut.Y); var zLerp = gnr.lerpCap(minIn, maxIn, minOut.Z, maxOut.Z); return function(d) { return { X: xLerp(d), Y: yLerp(d), Z: zLerp(d) }; }; }, vector2Color: function(v) { return { r: v.X, g: v.Y, b: v.Z }; }, vector: { product: function(v1, v2) { return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z; }, length: function(v) { return sqrt(gnr.vector.product(v, v)); } } } `) if err != nil { panic(err) } }
func DefineWithHandler(vm *otto.Otto, l *loop.Loop, h http.Handler) error { if err := promise.Define(vm, l); err != nil { return err } jsData := rice.MustFindBox("dist-fetch").MustString("bundle.js") smData := rice.MustFindBox("dist-fetch").MustString("bundle.js.map") s, err := vm.CompileWithSourceMap("fetch-bundle.js", jsData, smData) if err != nil { return err } if _, err := vm.Run(s); err != nil { return err } vm.Set("__private__fetch_execute", func(c otto.FunctionCall) otto.Value { jsReq := c.Argument(0).Object() jsRes := c.Argument(1).Object() cb := c.Argument(2) method := mustValue(jsReq.Get("method")).String() urlStr := mustValue(jsReq.Get("url")).String() jsBody := mustValue(jsReq.Get("body")) var body io.Reader if jsBody.IsString() { body = strings.NewReader(jsBody.String()) } t := &fetchTask{ jsReq: jsReq, jsRes: jsRes, cb: cb, } l.Add(t) go func() { defer l.Ready(t) req, err := http.NewRequest(method, urlStr, body) if err != nil { t.err = err return } if h != nil && urlStr[0] == '/' { res := httptest.NewRecorder() h.ServeHTTP(res, req) t.status = res.Code t.statusText = http.StatusText(res.Code) t.headers = res.Header() t.body = res.Body.Bytes() } else { res, err := http.DefaultClient.Do(req) if err != nil { t.err = err return } d, err := ioutil.ReadAll(res.Body) if err != nil { t.err = err return } t.status = res.StatusCode t.statusText = res.Status t.headers = res.Header t.body = d } }() return otto.UndefinedValue() }) return nil }
func (ctrl *JsController) addGetter(o *otto.Otto) { o.Set("get", func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) <= 0 { glog.Errorf("GET: Missing arguments") return newError(o, fmt.Errorf("GET: missing arguments")) } // Convert first argument, expect either string with url or list of strings upstreamsI, err := call.Argument(0).Export() if err != nil { glog.Errorf("GET: Failed to export first argument: %s", err) return newError(o, err) } upstreams, err := toStringArray(upstreamsI) if err != nil { glog.Errorf("GET: Failed to convert upstreams: %s", err) return newError(o, err) } // Second argument may be absent var query client.MultiDict if len(call.ArgumentList) > 1 { queryI, err := call.Argument(1).Export() if err != nil { glog.Errorf("GET: Failed to export first argument: %s", err) return newError(o, err) } dict, err := toMultiDict(queryI) if err != nil { glog.Errorf("GET: Failed: %s", err) return newError(o, err) } query = dict } // Third argument is optional username/password object var auth *netutils.BasicAuth if len(call.ArgumentList) > 2 { queryI, err := call.Argument(2).Export() if err != nil { glog.Errorf("GET: Failed: %s", err) return newError(o, err) } creds, err := toBasicAuth(queryI) if err != nil { glog.Errorf("GET: Failed: %s", err) return newError(o, err) } auth = creds } writer := NewResponseWriter() err = ctrl.Client.Get(writer, upstreams, query, auth) if err != nil { glog.Errorf("GET: Failed: %s", err) return newError(o, err) } reply := writer.ToReply() converted, err := o.ToValue(reply) if err != nil { glog.Errorf("GET: Failed: %s", err) return newError(o, err) } return converted }) }
func (ba *BindingApp) UpdateJavascriptRuntime(ctx *Context, runtime *otto.Otto) error { runtime.Set("Napoleon", "Dynamite") return nil }
func DefineWithHandler(vm *otto.Otto, l *loop.Loop, h http.Handler) error { if err := promise.Define(vm, l); err != nil { return err } s, err := vm.Compile("fetch.js", rice.MustFindBox("dist-fetch").MustString("bundle.js")) if err != nil { return err } if _, err := vm.Run(s); err != nil { return err } vm.Set("__private__fetch_execute", func(c otto.FunctionCall) otto.Value { jsReq := c.Argument(0).Object() jsRes := c.Argument(1).Object() cb := c.Argument(2) method := mustValue(jsReq.Get("method")).String() urlStr := mustValue(jsReq.Get("url")).String() jsBody := mustValue(jsReq.Get("body")) var body io.Reader if jsBody.IsString() { body = strings.NewReader(jsBody.String()) } t := &fetchTask{ jsReq: jsReq, jsRes: jsRes, cb: cb, } l.Add(t) go func() { defer l.Ready(t) req, err := http.NewRequest(method, urlStr, body) if err != nil { t.err = err return } if h != nil && urlStr[0] == '/' { res := httptest.NewRecorder() h.ServeHTTP(res, req) jsRes.Set("status", res.Code) jsRes.Set("statusText", http.StatusText(res.Code)) h := mustValue(jsRes.Get("headers")).Object() for k, vs := range res.Header() { for _, v := range vs { if _, err := h.Call("append", k, v); err != nil { t.err = err return } } } jsRes.Set("_body", string(res.Body.Bytes())) } else { res, err := http.DefaultClient.Do(req) if err != nil { t.err = err return } jsRes.Set("status", res.StatusCode) jsRes.Set("statusText", res.Status) h := mustValue(jsRes.Get("headers")).Object() for k, vs := range res.Header { for _, v := range vs { if _, err := h.Call("append", k, v); err != nil { t.err = err return } } } d, err := ioutil.ReadAll(res.Body) if err != nil { t.err = err return } jsRes.Set("_body", string(d)) } }() return otto.UndefinedValue() }) return nil }