func getCompletions(vm *otto.Otto, line string) (results []string) { parts := strings.Split(line, ".") objRef := "this" prefix := line if len(parts) > 1 { objRef = strings.Join(parts[0:len(parts)-1], ".") prefix = parts[len(parts)-1] } obj, _ := vm.Object(objRef) if obj == nil { return nil } iterOwnAndConstructorKeys(vm, obj, func(k string) { if strings.HasPrefix(k, prefix) { if objRef == "this" { results = append(results, k) } else { results = append(results, strings.Join(parts[:len(parts)-1], ".")+"."+k) } } }) // e.g. web3<tab><tab> append dot since its an object if obj, _ = vm.Object(line); obj != nil { results = append(results, line+".") } sort.Strings(results) return results }
func reverseGremlinChainTo(env *otto.Otto, prevObj *otto.Object, tag string) (*otto.Object, *otto.Object) { env.Run("var _base_object = {}") base, err := env.Object("_base_object") if err != nil { glog.Error(err) return otto.NullValue().Object(), otto.NullValue().Object() } if isVertexChain(prevObj) { base.Set("_gremlin_type", "vertex") } else { base.Set("_gremlin_type", "morphism") } return reverseGremlinChainHelper(env, prevObj, base, tag) }
func iterOwnKeys(vm *otto.Otto, obj *otto.Object, f func(string)) { Object, _ := vm.Object("Object") rv, _ := Object.Call("getOwnPropertyNames", obj.Value()) gv, _ := rv.Export() switch gv := gv.(type) { case []interface{}: for _, v := range gv { f(v.(string)) } case []string: for _, v := range gv { f(v) } default: panic(fmt.Errorf("Object.getOwnPropertyNames returned unexpected type %T", gv)) } }
func OttoNewFunction(o *otto.Otto, f string) (otto.Value, error) { fn, err := o.Object("(" + f + ")") if err != nil { return otto.UndefinedValue(), fmt.Errorf("could not eval function, err: %v", err) } if fn.Class() != "Function" { return otto.UndefinedValue(), fmt.Errorf("fn not a function, was: %v", fn.Class()) } fnv := fn.Value() if fnv.Class() != "Function" { return otto.UndefinedValue(), fmt.Errorf("fnv not a function, was: %v", fnv.Class()) } return fnv, nil }
func OttoFromGo(o *otto.Otto, v interface{}) (otto.Value, error) { jv, err := json.Marshal(v) if err != nil { return otto.UndefinedValue(), fmt.Errorf("could not jsonify v, err: %v", err) } obj, err := o.Object("({v:" + string(jv) + "})") if err != nil { return otto.UndefinedValue(), fmt.Errorf("could not convert jv, err: %v", err) } objv, err := obj.Get("v") if err != nil { return otto.UndefinedValue(), fmt.Errorf("could not convert obj, err: %v", err) } return objv, nil }
func reverseGremlinChainHelper(env *otto.Otto, chain *otto.Object, newBase *otto.Object, tag string) (*otto.Object, *otto.Object) { kindVal, _ := chain.Get("_gremlin_type") kind, _ := kindVal.ToString() if tag != "" { if kind == "tag" { tags := getStringArgs(chain) for _, t := range tags { if t == tag { return newBase, chain } } } } if kind == "morphism" || kind == "vertex" { return newBase, chain } var newKind string switch kind { case "in": newKind = "out" case "out": newKind = "in" default: newKind = kind } prev, _ := chain.Get("_gremlin_prev") env.Run("var out = {}") out, _ := env.Object("out") out.Set("_gremlin_type", newKind) values, _ := chain.Get("_gremlin_values") out.Set("_gremlin_values", values) back, _ := chain.Get("_gremlin_back_chain") out.Set("_gremlin_back_chain", back) out.Set("_gremlin_prev", newBase) strings, _ := chain.Get("string_args") out.Set("string_args", strings) return reverseGremlinChainHelper(env, prev.Object(), out, tag) }
func getCompletions(vm *otto.Otto, line string) (results []string) { parts := strings.Split(line, ".") objRef := "this" prefix := line if len(parts) > 1 { objRef = strings.Join(parts[0:len(parts)-1], ".") prefix = parts[len(parts)-1] } obj, _ := vm.Object(objRef) if obj == nil { return nil } iterOwnAndConstructorKeys(vm, obj, func(k string) { if strings.HasPrefix(k, prefix) { if objRef == "this" { results = append(results, k) } else { results = append(results, strings.Join(parts[:len(parts)-1], ".")+"."+k) } } }) // Append opening parenthesis (for functions) or dot (for objects) // if the line itself is the only completion. if len(results) == 1 && results[0] == line { obj, _ := vm.Object(line) if obj != nil { if obj.Class() == "Function" { results[0] += "(" } else { results[0] += "." } } } sort.Strings(results) return results }
func setupGremlin(env *otto.Otto, ses *Session) { graph, _ := env.Object("graph = {}") graph.Set("Vertex", func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, err := call.Otto.Object("out") if err != nil { glog.Error(err.Error()) return otto.TrueValue() } out.Set("_gremlin_type", "vertex") outStrings := concatStringArgs(call) if len(*outStrings) > 0 { out.Set("string_args", *outStrings) } embedTraversals(env, ses, out) embedFinals(env, ses, out) return out.Value() }) graph.Set("Morphism", func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", "morphism") embedTraversals(env, ses, out) return out.Value() }) graph.Set("Emit", func(call otto.FunctionCall) otto.Value { value := call.Argument(0) if value.IsDefined() { ses.SendResult(&GremlinResult{metaresult: false, err: "", val: &value, actualResults: nil}) } return otto.NullValue() }) env.Run("graph.V = graph.Vertex") env.Run("graph.M = graph.Morphism") env.Run("g = graph") }
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) } }