// NewAccount asks the user for the password and than executes the jeth.newAccount callback in the jsre func (self *Jeth) NewAccount(call otto.FunctionCall) (response otto.Value) { var passwd string if len(call.ArgumentList) == 0 { var err error passwd, err = Stdin.PasswordPrompt("Passphrase: ") if err != nil { return otto.FalseValue() } passwd2, err := Stdin.PasswordPrompt("Repeat passphrase: ") if err != nil { return otto.FalseValue() } if passwd != passwd2 { fmt.Println("Passphrases don't match") return otto.FalseValue() } } else if len(call.ArgumentList) == 1 && call.Argument(0).IsString() { passwd, _ = call.Argument(0).ToString() } else { fmt.Println("expected 0 or 1 string argument") return otto.FalseValue() } ret, err := call.Otto.Call("jeth.newAccount", nil, passwd) if err == nil { return ret } fmt.Println(err) return otto.FalseValue() }
// Add Response API func plurk_AddResponse(call otto.FunctionCall) otto.Value { plurkID, _ := call.Argument(0).ToInteger() message, _ := call.Argument(1).ToString() qualifier, _ := call.Argument(2).ToString() if plurkID == 0 { logger.Error("Plurk ID not specify, add response failed!") return otto.FalseValue() } if len(message) <= 0 || message == "undefined" { logger.Error("No plurk content specify, add response failed!") return otto.FalseValue() } if qualifier == "undefined" { qualifier = ":" } responses := client.GetResponses() res, err := responses.ResponseAdd(int(plurkID), message, qualifier) if err != nil { logger.Error("Add response failed, because %s", err.Error()) } logger.Info("Add response success, content is %s", res.RawContent) return otto.TrueValue() }
func (pm *PluginManager) InitUtilsJSBridge() { bridge := &pmUtilsJSBridge{ GetPage: func(call otto.FunctionCall) otto.Value { var err error switch { case len(call.ArgumentList) == 1 && call.ArgumentList[0].IsString(): if page, err := utils.GetPage(call.Argument(0).String()); err == nil { if val, err := pm.js.ToValue(page); err == nil { return val } } pm.log.Printf("[UTILS] GetPage errored: %s\n", err) case len(call.ArgumentList) == 3 && call.ArgumentList[0].IsString() && call.ArgumentList[1].IsString() && call.ArgumentList[2].IsString(): if page, err := utils.GetPageWithAuth(call.Argument(0).String(), call.Argument(1).String(), call.Argument(2).String()); err == nil { if val, err := pm.js.ToValue(page); err == nil { return val } } pm.log.Printf("[UTILS] GetPageWithAuth errored: %s\n", err) } return otto.FalseValue() }, ExtractURL: func(call otto.FunctionCall) otto.Value { var err error if len(call.ArgumentList) == 1 && call.ArgumentList[0].IsString() { if url, err := utils.ExtractURL(call.Argument(0).String()); err == nil { if val, err := pm.js.ToValue(url); err == nil { return val } } pm.log.Printf("[UTILS] ExtractURL errored: %s\n", err) } return otto.FalseValue() }, ExtractTitle: func(call otto.FunctionCall) otto.Value { var err error if len(call.ArgumentList) == 1 && call.ArgumentList[0].IsString() { if title, err := utils.ExtractTitle(call.Argument(0).String()); err == nil { if val, err := pm.js.ToValue(title); err == nil { return val } } pm.log.Printf("[UTILS] ExtractTitle errored: %s\n", err) } return otto.FalseValue() }, Sleep: func(call otto.FunctionCall) otto.Value { var err error if len(call.ArgumentList) == 1 && call.ArgumentList[0].IsNumber() { if i, err := call.Argument(0).ToInteger(); err == nil { utils.Sleep(i) return otto.TrueValue() } pm.log.Printf("[UTILS] Sleep errored: %s\n", err) } return otto.FalseValue() }, } pm.js.Set("UTILS", bridge) }
func (js *jsre) unlock(call otto.FunctionCall) otto.Value { addr, err := call.Argument(0).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } seconds, err := call.Argument(2).ToInteger() if err != nil { fmt.Println(err) return otto.FalseValue() } arg := call.Argument(1) var passphrase string if arg.IsUndefined() { fmt.Println("Please enter a passphrase now.") passphrase, err = readPassword("Passphrase: ", true) if err != nil { utils.Fatalf("%v", err) } } else { passphrase, err = arg.ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } } am := js.ethereum.AccountManager() err = am.TimedUnlock(common.FromHex(addr), passphrase, time.Duration(seconds)*time.Second) if err != nil { fmt.Printf("Unlock account failed '%v'\n", err) return otto.FalseValue() } return otto.TrueValue() }
// NewAccount asks the user for the password and than executes the jeth.newAccount callback in the jsre func (self *Jeth) NewAccount(call otto.FunctionCall) (response otto.Value) { if len(call.ArgumentList) == 0 { passwd, err := PromptPassword("Passphrase: ", true) if err != nil { return otto.FalseValue() } passwd2, err := PromptPassword("Repeat passphrase: ", true) if err != nil { return otto.FalseValue() } if passwd != passwd2 { fmt.Println("Passphrases don't match") return otto.FalseValue() } cmd := fmt.Sprintf("jeth.newAccount('%s')", passwd) if val, err := call.Otto.Run(cmd); err == nil { return val } } else { fmt.Println("New account doesn't expect argument(s), you will be prompted for a password") } return otto.FalseValue() }
func (js *jsre) resend(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) == 0 { fmt.Println("first argument must be a transaction") return otto.FalseValue() } v, err := call.Argument(0).Export() if err != nil { fmt.Println(err) return otto.FalseValue() } if tx, ok := v.(*tx); ok { gl, gp := tx.GasLimit, tx.GasPrice if len(call.ArgumentList) > 1 { gp = call.Argument(1).String() } if len(call.ArgumentList) > 2 { gl = call.Argument(2).String() } ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data) if err != nil { fmt.Println(err) return otto.FalseValue() } js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx}) return js.re.ToVal(ret) } fmt.Println("first argument must be a transaction") return otto.FalseValue() }
// Add Plurk API func plurk_AddPlurk(call otto.FunctionCall) otto.Value { message, _ := call.Argument(0).ToString() qualifier, _ := call.Argument(1).ToString() lang, _ := call.Argument(2).ToString() // No message specify, return error if len(message) <= 0 { return otto.FalseValue() } // Default qualifier if qualifier == "undefined" { qualifier = ":" } if lang == "undefined" { lang = "en" } timeline := client.GetTimeline() res, err := timeline.PlurkAdd(message, qualifier, make([]int, 0), false, lang, true) if err != nil { logger.Error("Add Plurk failed, because %s", err.Error()) return otto.FalseValue() } logger.Info("New plurk added, content is %s", res.RawContent) return otto.TrueValue() }
func (i *instance) loadplugin(name string) error { b, err := ioutil.ReadFile(name) _, filename := filepath.Split(name) if _, ok := i.Pluginfuncs[filename]; ok { delete(i.Pluginfuncs, filename) delete(i.Plugindocs, filename) } if err != nil { return err } m := make(map[string]otto.Value) i.js.Set("Subscribe", func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) >= 2 && call.ArgumentList[0].IsString() && call.ArgumentList[1].IsFunction() { name := call.ArgumentList[0].String() f := call.ArgumentList[1] if strings.HasPrefix(name, "regex:") { _, err := regexp.Compile(name[len("regex:"):]) if err != nil { i.Irc.Privmsg(i.Irccfg.Channel, "Regex error: "+err.Error()+" - Regex subscribe was not successful") return otto.FalseValue() } } m[name] = f return otto.TrueValue() } else { return otto.FalseValue() } }) md := make(map[string]string) i.js.Set("Doc", func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) >= 2 && call.ArgumentList[0].IsString() && call.ArgumentList[1].IsString() { name := call.ArgumentList[0].String() doc := call.ArgumentList[1].String() md[name] = doc return otto.TrueValue() } else { return otto.FalseValue() } }) _, err = i.js.Run(string(b)) i.js.Set("Subscribe", nil) i.js.Set("Doc", nil) if err != nil { fmt.Println(err.Error()) return err } else { i.Pluginfuncs[filename] = m i.Plugindocs[filename] = md return nil } }
func NewExecutor(s stream.Stream) *Executor { e := &Executor{ incomingScripts: make(chan string), outgoingMsgs: make(chan string), incomingEvents: make(chan IncomingEvent), eventHandlers: make(map[string]map[string]otto.Value), } e.xmppStream = s e.vm = otto.New() send := func(call otto.FunctionCall) otto.Value { str, _ := call.Argument(0).ToString() e.outgoingMsgs <- str return otto.UndefinedValue() } addHandler := func(call otto.FunctionCall) otto.Value { evtName, err := call.Argument(0).ToString() handlerName, err := call.Argument(1).ToString() if err != nil { return otto.FalseValue() } val := call.Argument(2) if !val.IsFunction() { return otto.FalseValue() } handlers, ok := e.eventHandlers[evtName] if !ok { e.eventHandlers[evtName] = map[string]otto.Value{handlerName: val} } else { handlers[handlerName] = val } return otto.TrueValue() } listHandlers := func(call otto.FunctionCall) otto.Value { evtName, err := call.Argument(0).ToString() if err != nil { return otto.UndefinedValue() } list := []string{} for handlerName := range e.eventHandlers[evtName] { list = append(list, handlerName) } val, err := e.vm.ToValue(list) if err != nil { return otto.UndefinedValue() } else { return val } } chatLibrary, _ := e.vm.Object("Chat = {};") chatLibrary.Set("send", send) chatLibrary.Set("addEventHandler", addHandler) chatLibrary.Set("listEventHandlers", listHandlers) return e }
/* Executes a JS script from inside the currently executing JS code. Should only be called from inside an RPC routine. */ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { file, err := call.Argument(0).ToString() if err != nil { return otto.FalseValue() } if err := self.execWithoutEQ(file); err != nil { // loadScript is only called from inside js fmt.Println("err:", err) return otto.FalseValue() } return otto.TrueValue() }
func (js *jsre) addPeer(call otto.FunctionCall) otto.Value { nodeURL, err := call.Argument(0).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } err = js.ethereum.AddPeer(nodeURL) if err != nil { fmt.Println(err) return otto.FalseValue() } return otto.TrueValue() }
func (js *jsre) startMining(call otto.FunctionCall) otto.Value { _, err := call.Argument(0).ToInteger() if err != nil { fmt.Println(err) return otto.FalseValue() } // threads now ignored err = js.ethereum.StartMining() if err != nil { fmt.Println(err) return otto.FalseValue() } return otto.TrueValue() }
func (js *jsre) newAccount(call otto.FunctionCall) otto.Value { arg := call.Argument(0) var passphrase string if arg.IsUndefined() { fmt.Println("The new account will be encrypted with a passphrase.") fmt.Println("Please enter a passphrase now.") auth, err := readPassword("Passphrase: ", true) if err != nil { utils.Fatalf("%v", err) } confirm, err := readPassword("Repeat Passphrase: ", false) if err != nil { utils.Fatalf("%v", err) } if auth != confirm { utils.Fatalf("Passphrases did not match.") } passphrase = auth } else { var err error passphrase, err = arg.ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } } acct, err := js.ethereum.AccountManager().NewAccount(passphrase) if err != nil { fmt.Printf("Could not create the account: %v", err) return otto.UndefinedValue() } return js.re.ToVal("0x" + common.Bytes2Hex(acct.Address)) }
func (js *jsre) importChain(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) == 0 { fmt.Println("err: require file name") return otto.FalseValue() } fn, err := call.Argument(0).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil { fmt.Println("Import error: ", err) return otto.FalseValue() } return otto.TrueValue() }
// UnlockAccount asks the user for the password and than executes the jeth.UnlockAccount callback in the jsre. // It will need the public address for the account to unlock as first argument. // The second argument is an optional string with the password. If not given the user is prompted for the password. // The third argument is an optional integer which specifies for how long the account will be unlocked (in seconds). func (self *Jeth) UnlockAccount(call otto.FunctionCall) (response otto.Value) { var account, passwd otto.Value duration := otto.NullValue() if !call.Argument(0).IsString() { fmt.Println("first argument must be the account to unlock") return otto.FalseValue() } account = call.Argument(0) // if password is not given or as null value -> ask user for password if call.Argument(1).IsUndefined() || call.Argument(1).IsNull() { fmt.Printf("Unlock account %s\n", account) if input, err := Stdin.PasswordPrompt("Passphrase: "); err != nil { throwJSExeception(err.Error()) } else { passwd, _ = otto.ToValue(input) } } else { if !call.Argument(1).IsString() { throwJSExeception("password must be a string") } passwd = call.Argument(1) } // third argument is the duration how long the account must be unlocked. // verify that its a number. if call.Argument(2).IsDefined() && !call.Argument(2).IsNull() { if !call.Argument(2).IsNumber() { throwJSExeception("unlock duration must be a number") } duration = call.Argument(2) } // jeth.unlockAccount will send the request to the backend. if val, err := call.Otto.Call("jeth.unlockAccount", nil, account, passwd, duration); err == nil { return val } else { throwJSExeception(err.Error()) } return otto.FalseValue() }
func registerVM(vm *modules.JsVm) otto.Value { obj, _ := vm.Object("({})") obj.Set("newSession", func(c otto.FunctionCall) otto.Value { str, _ := c.Argument(0).ToString() session, err := mgo.Dial(str) if err != nil { panic(err) } //defer session.Close() // Optional. Switch the session to a monotonic behavior. //session.SetMode(mgo.Monotonic, true) sess, _ := c.Otto.ToValue(session) return sess }) obj.Set("one", func(c otto.FunctionCall) otto.Value { queryObj, _ := c.Argument(0).Export() query, ok := queryObj.(*mgo.Query) if ok { out := map[string]interface{}{} query.One(&out) val, _ := vm.ToValue(out) return val } return otto.FalseValue() }) obj.Set("all", func(c otto.FunctionCall) otto.Value { queryObj, _ := c.Argument(0).Export() query, ok := queryObj.(*mgo.Query) if ok { out := []map[string]interface{}{} query.All(&out) val, _ := vm.ToValue(out) return val } return otto.FalseValue() }) return obj.Value() }
// UnlockAccount asks the user for the password and than executes the jeth.UnlockAccount callback in the jsre func (self *Jeth) UnlockAccount(call otto.FunctionCall) (response otto.Value) { var cmd, account, passwd string timeout := int64(300) var ok bool if len(call.ArgumentList) == 0 { fmt.Println("expected address of account to unlock") return otto.FalseValue() } if len(call.ArgumentList) >= 1 { if accountExport, err := call.Argument(0).Export(); err == nil { if account, ok = accountExport.(string); ok { if len(call.ArgumentList) == 1 { fmt.Printf("Unlock account %s\n", account) passwd, err = PromptPassword("Passphrase: ", true) if err != nil { return otto.FalseValue() } } } } } if len(call.ArgumentList) >= 2 { if passwdExport, err := call.Argument(1).Export(); err == nil { passwd, _ = passwdExport.(string) } } if len(call.ArgumentList) >= 3 { if timeoutExport, err := call.Argument(2).Export(); err == nil { timeout, _ = timeoutExport.(int64) } } cmd = fmt.Sprintf("jeth.unlockAccount('%s', '%s', %d)", account, passwd, timeout) if val, err := call.Otto.Run(cmd); err == nil { return val } return otto.FalseValue() }
// loadScript executes a JS script from inside the currently executing JS code. func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { file, err := call.Argument(0).ToString() if err != nil { // TODO: throw exception return otto.FalseValue() } file = common.AbsolutePath(self.assetPath, file) source, err := ioutil.ReadFile(file) if err != nil { // TODO: throw exception return otto.FalseValue() } if _, err := compileAndRun(call.Otto, file, source); err != nil { // TODO: throw exception fmt.Println("err:", err) return otto.FalseValue() } // TODO: return evaluation result return otto.TrueValue() }
func (pm *PluginManager) InitDebugJSBridge() { bridge := &pmDebugJSBridge{ StackTrace: func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) == 0 { debug.PrintStack() return otto.TrueValue() } return otto.FalseValue() }, } pm.js.Set("DEBUG", bridge) }
// SleepBlocks will wait for a specified number of new blocks or max for a // given of seconds. sleepBlocks(nBlocks[, maxSleep]). func (self *Jeth) SleepBlocks(call otto.FunctionCall) (response otto.Value) { nBlocks := int64(0) maxSleep := int64(9999999999999999) // indefinitely nArgs := len(call.ArgumentList) if nArgs == 0 { throwJSExeception("usage: sleepBlocks(<n blocks>[, max sleep in seconds])") } if nArgs >= 1 { if call.Argument(0).IsNumber() { nBlocks, _ = call.Argument(0).ToInteger() } else { throwJSExeception("expected number as first argument") } } if nArgs >= 2 { if call.Argument(1).IsNumber() { maxSleep, _ = call.Argument(1).ToInteger() } else { throwJSExeception("expected number as second argument") } } // go through the console, this will allow web3 to call the appropriate // callbacks if a delayed response or notification is received. currentBlockNr := func() int64 { result, err := call.Otto.Run("eth.blockNumber") if err != nil { throwJSExeception(err.Error()) } blockNr, err := result.ToInteger() if err != nil { throwJSExeception(err.Error()) } return blockNr } targetBlockNr := currentBlockNr() + nBlocks deadline := time.Now().Add(time.Duration(maxSleep) * time.Second) for time.Now().Before(deadline) { if currentBlockNr() >= targetBlockNr { return otto.TrueValue() } time.Sleep(time.Second) } return otto.FalseValue() }
func (p *Plugin) jsEnv(event *irc.Event) otto.Value { obj, _ := p.js.Object("({})") obj.Set("event", p.eventToValue(event)) obj.Set("log", func(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) == 1 && call.ArgumentList[0].IsString() { p.log.Println(call.ArgumentList[0].String()) return otto.TrueValue() } else { return otto.FalseValue() } }) return obj.Value() }
// 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 (js *jsre) startRPC(call otto.FunctionCall) otto.Value { addr, err := call.Argument(0).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } port, err := call.Argument(1).ToInteger() if err != nil { fmt.Println(err) return otto.FalseValue() } corsDomain := js.corsDomain if len(call.ArgumentList) > 2 { corsDomain, err = call.Argument(2).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } } config := rpc.RpcConfig{ ListenAddress: addr, ListenPort: uint(port), CorsDomain: corsDomain, } xeth := xeth.New(js.ethereum, nil) err = rpc.Start(xeth, config) if err != nil { fmt.Printf(err.Error()) return otto.FalseValue() } return otto.TrueValue() }
// SleepBlocks will block the console for a specified number of new blocks optionally // until the given timeout is reached. func (b *bridge) SleepBlocks(call otto.FunctionCall) (response otto.Value) { var ( blocks = int64(0) sleep = int64(9999999999999999) // indefinitely ) // Parse the input parameters for the sleep nArgs := len(call.ArgumentList) if nArgs == 0 { throwJSException("usage: sleepBlocks(<n blocks>[, max sleep in seconds])") } if nArgs >= 1 { if call.Argument(0).IsNumber() { blocks, _ = call.Argument(0).ToInteger() } else { throwJSException("expected number as first argument") } } if nArgs >= 2 { if call.Argument(1).IsNumber() { sleep, _ = call.Argument(1).ToInteger() } else { throwJSException("expected number as second argument") } } // go through the console, this will allow web3 to call the appropriate // callbacks if a delayed response or notification is received. blockNumber := func() int64 { result, err := call.Otto.Run("eth.blockNumber") if err != nil { throwJSException(err.Error()) } block, err := result.ToInteger() if err != nil { throwJSException(err.Error()) } return block } // Poll the current block number until either it ot a timeout is reached targetBlockNr := blockNumber() + blocks deadline := time.Now().Add(time.Duration(sleep) * time.Second) for time.Now().Before(deadline) { if blockNumber() >= targetBlockNr { return otto.TrueValue() } time.Sleep(time.Second) } return otto.FalseValue() }
func InjectLevelDB(jsEngine *JSEngine, db *leveldb.DB) { jsEngine.Run("var db = {};") dbValue, _ := jsEngine.Get("db") dbObj := dbValue.Object() dbObj.Set("put", func(call otto.FunctionCall) otto.Value { key, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } value, err := call.Argument(1).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } err = db.Put([]byte(key), []byte(value), nil) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } return otto.TrueValue() }) dbObj.Set("get", func(call otto.FunctionCall) otto.Value { key, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } data, err := db.Get([]byte(key), nil) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } v, _ := otto.ToValue(string(data)) return v }) dbObj.Set("remove", func(call otto.FunctionCall) otto.Value { key, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } err = db.Delete([]byte(key), nil) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } return otto.TrueValue() }) }
func TestExist(t *testing.T) { js := otto.New() assert.False(t, Exist(js, "myVar")) js.Set("myVar", otto.TrueValue()) assert.True(t, Exist(js, "myVar"), "true should exist") js.Set("myVar", otto.FalseValue()) assert.True(t, Exist(js, "myVar"), "false still exists") js.Set("myVar", otto.UndefinedValue()) assert.False(t, Exist(js, "myVar"), "undefined doesn't exist") }
func TestSetOnce(t *testing.T) { js := otto.New() if didSet, err := SetOnce(js, "myVar", otto.TrueValue()); assert.NoError(t, err) { assert.True(t, didSet) if val, err := js.Get("myVar"); assert.NoError(t, err) { if valBool, err := val.ToBoolean(); assert.NoError(t, err) { assert.True(t, valBool) } } } if didSet, err := SetOnce(js, "myVar", otto.FalseValue()); assert.NoError(t, err) { assert.False(t, didSet) if val, err := js.Get("myVar"); assert.NoError(t, err) { if valBool, err := val.ToBoolean(); assert.NoError(t, err) { assert.True(t, valBool) } } } }
func InjectIntoOtto(jsEngine *js.JSEngine) { jsEngine.Run("var fs = {};") fsValue, _ := jsEngine.Get("fs") fsObj := fsValue.Object() fsObj.Set("readFile", func(call otto.FunctionCall) otto.Value { filename, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } bs, err := ioutil.ReadFile(filename) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } val, err := otto.ToValue(string(bs)) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } return val }) fsObj.Set("writeFile", func(call otto.FunctionCall) otto.Value { filename, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } data, err := call.Argument(1).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } err = ioutil.WriteFile(filename, []byte(data), 0777) if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } return otto.TrueValue() }) }
func reduceViewResult(bucket Bucket, result *ViewResult, p *ViewParams, reduceFunction string) (*ViewResult, error) { groupLevel := 0 if p.Group { groupLevel = 0x7fffffff } if p.GroupLevel > 0 { groupLevel = int(p.GroupLevel) } o := newReducer() fnv, err := OttoNewFunction(o, reduceFunction) if err != nil { return result, err } initialCapacity := 200 results := make([]*ViewRow, 0, initialCapacity) groupKeys := make([]interface{}, 0, initialCapacity) groupValues := make([]interface{}, 0, initialCapacity) i := 0 j := 0 for i < len(result.Rows) { groupKeys = groupKeys[:0] groupValues = groupValues[:0] startRow := result.Rows[i] groupKey := ArrayPrefix(startRow.Key, groupLevel) for j = i; j < len(result.Rows); j++ { row := result.Rows[j] rowKey := ArrayPrefix(row.Key, groupLevel) if walrus.CollateJSON(groupKey, rowKey) < 0 { break } groupKeys = append(groupKeys, row.Key) groupValues = append(groupValues, row.Value) } i = j okeys, err := OttoFromGoArray(o, groupKeys) if err != nil { return result, err } ovalues, err := OttoFromGoArray(o, groupValues) if err != nil { return result, err } ores, err := fnv.Call(fnv, okeys, ovalues, otto.FalseValue()) if err != nil { return result, fmt.Errorf("call reduce err: %v, reduceFunction: %v, %v, %v", err, reduceFunction, okeys, ovalues) } gres, err := ores.Export() if err != nil { return result, fmt.Errorf("converting reduce result err: %v", err) } results = append(results, &ViewRow{Key: groupKey, Value: gres}) } result.Rows = results return result, nil }
func InjectIntoOtto(jsEngine *js.JSEngine, manager *EventManager) { jsEngine.Run("var events = {};") eventsValue, _ := jsEngine.Get("events") eventsObj := eventsValue.Object() eventsObj.Set("on", func(call otto.FunctionCall) otto.Value { topic, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } fn := call.Argument(1) id := manager.On(topic, func(topic string, payload interface{}) { t, _ := otto.ToValue(topic) p, _ := otto.ToValue(payload) _, err := fn.Call(fn, t, p) if err != nil { log.Println("Error in JS callback:", err.Error()) } }) i, _ := otto.ToValue(id) return i }) eventsObj.Set("once", func(call otto.FunctionCall) otto.Value { topic, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } fn := call.Argument(1) manager.Once(topic, func(topic string, payload interface{}) { t, _ := otto.ToValue(topic) p, _ := otto.ToValue(payload) _, err := fn.Call(fn, t, p) if err != nil { log.Println("Error in JS callback:", err.Error()) } }) return otto.TrueValue() }) eventsObj.Set("many", func(call otto.FunctionCall) otto.Value { topic, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } count, err := call.Argument(1).ToInteger() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } fn := call.Argument(2) manager.Many(topic, int(count), func(topic string, payload interface{}) { t, _ := otto.ToValue(topic) p, _ := otto.ToValue(payload) _, err := fn.Call(fn, t, p) if err != nil { log.Println("Error in JS callback:", err.Error()) } }) return otto.TrueValue() }) eventsObj.Set("off", func(call otto.FunctionCall) otto.Value { id, err := call.Argument(0).ToInteger() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } res := manager.Off(id) r, _ := otto.ToValue(res) return r }) eventsObj.Set("emit", func(call otto.FunctionCall) otto.Value { topic, err := call.Argument(0).ToString() if err != nil { log.Println("Error:", err.Error()) return otto.FalseValue() } payload := call.Argument(1) manager.Emit(topic, payload) return otto.TrueValue() }) }