// pipelines in javascript are chainable, you take in a pipeline, and you return a pipeline // we just generalize some of that logic here func (js *JavascriptBuilder) setFunc(obj *otto.Object, token string, fn func(string, Node, otto.FunctionCall) (Node, error)) error { return obj.Set(token, func(call otto.FunctionCall) otto.Value { this, _ := call.This.Export() node, err := CreateNode(this) if err != nil { js.err = err return otto.NullValue() } node, err = fn(token, node, call) if err != nil { js.err = err return otto.NullValue() } o, err := node.Object() if err != nil { js.err = err return otto.NullValue() } js.setFunc(o, "transform", js.transform) js.setFunc(o, "save", js.save) return o.Value() }) }
func getString(obj *otto.Object, name string) (string, error) { v, err := obj.Get(name) if err != nil { return "", err } return v.ToString() }
func (ctx ppctx) fields(obj *otto.Object) []string { var ( vals, methods []string seen = make(map[string]bool) ) add := func(k string) { if seen[k] || boringKeys[k] { return } seen[k] = true if v, _ := obj.Get(k); v.IsFunction() { methods = append(methods, k) } else { vals = append(vals, k) } } // add own properties ctx.doOwnProperties(obj.Value(), add) // add properties of the constructor if cp := constructorPrototype(obj); cp != nil { ctx.doOwnProperties(cp.Value(), add) } sort.Strings(vals) sort.Strings(methods) return append(vals, methods...) }
func (wk *worker) gremlinFollowR(kind string, prev *otto.Object, env *otto.Otto) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", kind) out.Set("_gremlin_values", call.ArgumentList) args := argsOf(call) if len(args) > 0 { out.Set("string_args", args) } if len(call.ArgumentList) == 0 { return prev.Value() } arg := call.Argument(0) if isVertexChain(arg.Object()) { return prev.Value() } newChain, _ := reverseGremlinChainTo(call.Otto, arg.Object(), "") out.Set("_gremlin_prev", prev) out.Set("_gremlin_followr", newChain) wk.embedTraversals(env, out) if isVertexChain(call.This.Object()) { wk.embedFinals(env, out) } return out.Value() } }
func getViaData(obj *otto.Object) (predicates []interface{}, tags []string, ok bool) { argList, _ := obj.Get("_gremlin_values") if argList.Class() != "GoArray" { clog.Errorf("How is arglist not an array? Return nothing. %v", argList.Class()) return nil, nil, false } argArray := argList.Object() lengthVal, _ := argArray.Get("length") length, _ := lengthVal.ToInteger() if length == 0 { predicates = []interface{}{} } else { zero, _ := argArray.Get("0") predicates = buildPathFromValue(zero) } if length >= 2 { one, _ := argArray.Get("1") if one.IsString() { tags = append(tags, one.String()) } else if one.Class() == "Array" { tags = stringsFrom(one.Object()) } } ok = true return }
func gremlinFollowR(kind string, prevObj *otto.Object, env *otto.Otto, ses *GremlinSession) func(otto.FunctionCall) otto.Value { return func(call otto.FunctionCall) otto.Value { call.Otto.Run("var out = {}") out, _ := call.Otto.Object("out") out.Set("_gremlin_type", kind) out.Set("_gremlin_values", call.ArgumentList) outStrings := concatStringArgs(call) if len(*outStrings) > 0 { out.Set("string_args", *outStrings) } if len(call.ArgumentList) == 0 { return prevObj.Value() } arg := call.Argument(0) if isVertexChain(arg.Object()) { return prevObj.Value() } newChain, _ := reverseGremlinChainTo(call.Otto, arg.Object(), "") out.Set("_gremlin_prev", prevObj) out.Set("_gremlin_followr", newChain) embedTraversals(env, ses, out) if isVertexChain(call.This.Object()) { embedFinals(env, ses, out) } return out.Value() } }
func getInt(obj *otto.Object, name string) (int64, error) { v, err := obj.Get(name) if err != nil { return -1, err } return v.ToInteger() }
func propertiesOf(obj *otto.Object, name string) []string { val, _ := obj.Get(name) if val.IsUndefined() { return nil } export, _ := val.Export() return export.([]string) }
func getFirstArgAsMorphismChain(obj *otto.Object) *otto.Object { arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if isVertexChain(firstArg.Object()) { return nil } return firstArg.Object() }
func constructorPrototype(obj *otto.Object) *otto.Object { if v, _ := obj.Get("constructor"); v.Object() != nil { if v, _ = v.Object().Get("prototype"); v.Object() != nil { return v.Object() } } return nil }
func debugChain(obj *otto.Object) bool { val, _ := obj.Get("_gremlin_type") glog.V(2).Infoln(val) val, _ = obj.Get("_gremlin_prev") if val.IsObject() { return debugChain(val.Object()) } return false }
func isVertexChain(obj *otto.Object) bool { val, _ := obj.Get("_gremlin_type") if val.String() == "vertex" { return true } val, _ = obj.Get("_gremlin_prev") if val.IsObject() { return isVertexChain(val.Object()) } return false }
func debugChain(obj *otto.Object) bool { val, _ := obj.Get("_gremlin_type") if clog.V(2) { clog.Infof("%v", val) } val, _ = obj.Get("_gremlin_prev") if val.IsObject() { return debugChain(val.Object()) } return false }
func getStrings(obj *otto.Object, field string) []string { strings := make([]string, 0) val, _ := obj.Get(field) if !val.IsUndefined() { export, _ := val.Export() array := export.([]interface{}) for _, arg := range array { strings = append(strings, arg.(string)) } } return strings }
func ResponseWriterToJso(o *otto.Object, w http.ResponseWriter) { o.Set("write", func(c otto.FunctionCall) otto.Value { text, _ := c.Argument(0).ToString() w.Write([]byte(text)) return otto.TrueValue() }) o.Set("writeHeader", func(c otto.FunctionCall) otto.Value { statusCode, _ := c.Argument(0).ToInteger() w.WriteHeader(int(statusCode)) return otto.TrueValue() }) }
func setHeader(o *otto.Object, h *http.Header) { header, _ := o.Get("header") headerIface, _ := header.Export() headerMap, ok := headerIface.(map[string]interface{}) if ok { for k, v := range headerMap { strV, ok := v.(string) if ok { h.Set(k, strV) } } } }
func stringsFrom(obj *otto.Object) []string { var output []string lengthValue, _ := obj.Get("length") length, _ := lengthValue.ToInteger() ulength := uint32(length) for i := uint32(0); i < ulength; i++ { name := strconv.FormatInt(int64(i), 10) value, err := obj.Get(name) if err != nil || !value.IsString() { continue } output = append(output, value.String()) } return output }
func getFirstArgAsInt64(obj *otto.Object) (int64, bool) { arg, err := obj.Get("_gremlin_values") if err != nil { return 0, false } firstArg, err := arg.Object().Get("0") if err != nil { return 0, false } if !firstArg.IsNumber() { return 0, false } v, err := firstArg.ToInteger() return v, err == nil }
func JsoToResponseWriter(respObj *otto.Object, w http.ResponseWriter) { contentTypeV, err := respObj.Get("contentType") if err == nil { contentType, _ := contentTypeV.ToString() w.Header().Set("Content-Type", contentType) } wHeader := w.Header() setHeader(respObj, &wHeader) codeV, err := respObj.Get("statusCode") if err == nil && codeV.IsDefined() { code, _ := codeV.ToInteger() w.WriteHeader(int(code)) } }
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 makeListOfStringsFromArrayValue(obj *otto.Object) []string { var output []string lengthValue, _ := obj.Get("length") length, _ := lengthValue.ToInteger() ulength := uint32(length) for index := uint32(0); index < ulength; index += 1 { name := strconv.FormatInt(int64(index), 10) value, err := obj.Get(name) if err != nil { continue } if !value.IsString() { continue } s, _ := value.ToString() output = append(output, s) } return output }
// Converts a JS array into a Go string array. func ottoArrayToStrings(array *otto.Object) []string { lengthVal, err := array.Get("length") if err != nil { return nil } length, err := lengthVal.ToInteger() if err != nil || length <= 0 { return nil } result := make([]string, 0, length) for i := 0; i < int(length); i++ { item, err := array.Get(strconv.Itoa(i)) if err == nil && item.IsString() { result = append(result, item.String()) } } return result }
func (ctx ppctx) fields(obj *otto.Object) []string { var ( vals, methods []string seen = make(map[string]bool) ) add := func(k string) { if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") { return } seen[k] = true if v, _ := obj.Get(k); v.IsFunction() { methods = append(methods, k) } else { vals = append(vals, k) } } iterOwnAndConstructorKeys(ctx.vm, obj, add) sort.Strings(vals) sort.Strings(methods) return append(vals, methods...) }
func buildInOutIterator(obj *otto.Object, ts graph.TripleStore, base graph.Iterator, isReverse bool) graph.Iterator { argList, _ := obj.Get("_gremlin_values") if argList.Class() != "GoArray" { glog.Errorln("How is arglist not an array? Return nothing.", argList.Class()) return graph.NewNullIterator() } argArray := argList.Object() lengthVal, _ := argArray.Get("length") length, _ := lengthVal.ToInteger() var predicateNodeIterator graph.Iterator if length == 0 { predicateNodeIterator = ts.GetNodesAllIterator() } else { zero, _ := argArray.Get("0") predicateNodeIterator = buildIteratorFromValue(zero, ts) } if length >= 2 { var tags []string one, _ := argArray.Get("1") if one.IsString() { s, _ := one.ToString() tags = append(tags, s) } else if one.Class() == "Array" { tags = makeListOfStringsFromArrayValue(one.Object()) } for _, tag := range tags { predicateNodeIterator.AddTag(tag) } } in, out := graph.Subject, graph.Object if isReverse { in, out = out, in } lto := graph.NewLinksToIterator(ts, base, in) and := graph.NewAndIterator() and.AddSubIterator(graph.NewLinksToIterator(ts, predicateNodeIterator, graph.Predicate)) and.AddSubIterator(lto) return graph.NewHasaIterator(ts, and, out) }
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 buildInOutIterator(obj *otto.Object, qs graph.QuadStore, base graph.Iterator, isReverse bool) graph.Iterator { argList, _ := obj.Get("_gremlin_values") if argList.Class() != "GoArray" { glog.Errorln("How is arglist not an array? Return nothing.", argList.Class()) return iterator.NewNull() } argArray := argList.Object() lengthVal, _ := argArray.Get("length") length, _ := lengthVal.ToInteger() var predicateNodeIterator graph.Iterator if length == 0 { predicateNodeIterator = qs.NodesAllIterator() } else { zero, _ := argArray.Get("0") predicateNodeIterator = buildIteratorFromValue(zero, qs) } if length >= 2 { var tags []string one, _ := argArray.Get("1") if one.IsString() { tags = append(tags, one.String()) } else if one.Class() == "Array" { tags = stringsFrom(one.Object()) } for _, tag := range tags { predicateNodeIterator.Tagger().Add(tag) } } in, out := quad.Subject, quad.Object if isReverse { in, out = out, in } lto := iterator.NewLinksTo(qs, base, in) and := iterator.NewAnd() and.AddSubIterator(iterator.NewLinksTo(qs, predicateNodeIterator, quad.Predicate)) and.AddSubIterator(lto) return iterator.NewHasA(qs, and, out) }
func convertObject(input *otto.Object) map[string]interface{} { output := map[string]interface{}{} if input == nil { return output } for _, key := range input.Keys() { v1, _ := input.Get(key) var trueValue interface{} if v1.IsBoolean() { trueValue, _ = v1.ToBoolean() } else if v1.IsNumber() { trueValue, _ = v1.ToInteger() } else { trueValue = v1.String() } output[key] = trueValue } return output }
func ottoToGoArray(array *otto.Object) ([]interface{}, error) { lengthVal, err := array.Get("length") if err != nil { return nil, err } length, err := lengthVal.ToInteger() if err != nil { return nil, err } result := make([]interface{}, length) for i := 0; i < int(length); i++ { item, err := array.Get(strconv.Itoa(i)) if err != nil { return nil, err } result[i], err = ottoToGo(item) if err != nil { return nil, err } } return result, nil }
func (ctx ppctx) isBigNumber(v *otto.Object) bool { // Handle numbers with custom constructor. if v, _ := v.Get("constructor"); v.Object() != nil { if strings.HasPrefix(toString(v.Object()), "function BigNumber") { return true } } // Handle default constructor. BigNumber, _ := ctx.vm.Object("BigNumber.prototype") if BigNumber == nil { return false } bv, _ := BigNumber.Call("isPrototypeOf", v) b, _ := bv.ToBoolean() return b }
func JsoToRequest(o *otto.Object) *http.Request { url, _ := o.Get("url") method, err := o.Get("method") body, _ := o.Get("body") methodStr, err := method.ToString() if method == otto.UndefinedValue() || err != nil { methodStr = "GET" } urlStr, _ := url.ToString() req, _ := http.NewRequest(methodStr, urlStr, nil) if body != otto.UndefinedValue() { str, err := body.ToString() if err == nil { req.Body = &ClosingBuffer{bytes.NewBufferString(str)} } } setHeader(o, &req.Header) return req }