Beispiel #1
0
// 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
}
Beispiel #2
0
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
	})
}
Beispiel #3
0
// 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
}
Beispiel #4
0
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
}
Beispiel #5
0
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)
	})

}
Beispiel #6
0
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
	})
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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)
			}
		}
	}
}
Beispiel #9
0
// 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

}
Beispiel #10
0
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)
	}
}
Beispiel #11
0
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,
	})
}
Beispiel #12
0
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
}
Beispiel #13
0
// 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)
}
Beispiel #14
0
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
}
Beispiel #15
0
// 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
}
Beispiel #16
0
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
}
Beispiel #17
0
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)
	}
}
Beispiel #18
0
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
}
Beispiel #19
0
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
	})
}
Beispiel #20
0
func (ba *BindingApp) UpdateJavascriptRuntime(ctx *Context, runtime *otto.Otto) error {
	runtime.Set("Napoleon", "Dynamite")
	return nil
}
Beispiel #21
0
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
}