func TestFetchCallback(t *testing.T) { m := http.NewServeMux() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) }) s := httptest.NewServer(m) defer s.Close() vm := otto.New() l := loop.New(vm) if err := Define(vm, l); err != nil { panic(err) } ch := make(chan bool, 1) if err := vm.Set("__capture", func(s string) { defer func() { ch <- true }() if !strings.Contains(s, "hello") { panic(fmt.Errorf("expected to find `hello' in response")) } }); err != nil { panic(err) } must(l.EvalAndRun(`fetch('` + s.URL + `').then(function(r) { return r.text(); }).then(__capture)`)) <-ch }
func TestFetchWithHandler(t *testing.T) { m := http.NewServeMux() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // these spaces are here so we can disambiguate between this and the // re-encoded data the javascript below spits out w.Write([]byte("[ 1 , 2 , 3 ]")) }) vm := otto.New() l := loop.New(vm) if err := DefineWithHandler(vm, l, m); err != nil { panic(err) } ch := make(chan bool, 1) if err := vm.Set("__capture", func(s string) { defer func() { ch <- true }() if s != `[1,2,3]` { panic(fmt.Errorf("expected data to be json, and for that json to be parsed")) } }); err != nil { panic(err) } must(l.EvalAndRun(`fetch('/').then(function(r) { return r.json(); }).then(function(d) { return setTimeout(__capture, 4, JSON.stringify(d)); })`)) <-ch }
func TestFetchWithHandlerParallel(t *testing.T) { m := http.NewServeMux() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) }) vm := otto.New() l := loop.New(vm) if err := DefineWithHandler(vm, l, m); err != nil { panic(err) } ch := make(chan bool, 1) if err := vm.Set("__capture", func(c otto.FunctionCall) otto.Value { defer func() { ch <- true }() return otto.UndefinedValue() }); err != nil { panic(err) } must(l.EvalAndRun(`Promise.all([1,2,3,4,5].map(function(i) { return fetch('/' + i); })).then(__capture)`)) <-ch }
func TestFetchHeaders(t *testing.T) { m := http.NewServeMux() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("header-one", "1") w.Header().Add("header-two", "2a") w.Header().Add("header-two", "2b") w.Write([]byte("hello")) }) s := httptest.NewServer(m) defer s.Close() vm := otto.New() l := loop.New(vm) if err := Define(vm, l); err != nil { panic(err) } ch := make(chan bool, 1) if err := vm.Set("__capture", func(s string) { defer func() { ch <- true }() if s != `{"header-one":["1"],"header-two":["2a","2b"]}` { panic(fmt.Errorf("expected headers to contain 1, 2a, and 2b")) } }); err != nil { panic(err) } must(l.EvalAndRun(`fetch('` + s.URL + `').then(function(r) { return __capture(JSON.stringify({ 'header-one': r.headers.getAll('header-one'), 'header-two': r.headers.getAll('header-two'), })); })`)) <-ch }
func TestFetch(t *testing.T) { m := http.NewServeMux() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) }) s := httptest.NewServer(m) defer s.Close() vm := otto.New() l := loop.New(vm) if err := Define(vm, l); err != nil { panic(err) } must(l.EvalAndRun(`fetch('` + s.URL + `').then(function(r) { return r.text(); }).then(function(d) { if (d.indexOf('hellox') === -1) { throw new Error('what'); } });`)) }
func main() { logrus.StandardLogger().Level = logrus.DebugLevel logrus.Debug("starting up") baseVM := otto.New() smRead := logDuration("read sourcemap") smData, err := ioutil.ReadFile("../client/public/bundle.server.js.map") if err != nil { panic(err) } smRead() smParse := logDuration("parse sourcemap") sm, err := sourcemap.Read(bytes.NewReader(smData)) if err != nil { panic(err) } smParse() jsRead := logDuration("read javascript") jsData, err := ioutil.ReadFile("../client/public/bundle.server.js") if err != nil { panic(err) } jsRead() jsCompiled := logDuration("compile javascript") s, err := baseVM.CompileWithSourceMap("bundle.js", string(jsData), &sm) if err != nil { panic(err) } jsCompiled() jsInitialised := logDuration("initialise javascript") if _, err := baseVM.Run(s); err != nil { panic(err) } jsInitialised() tpl, err := template.ParseFiles("./index.template") if err != nil { panic(err) } apiRouter := mux.NewRouter() apiRouter.Path("/api/v1/posts").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { posts := `[ {"id":1,"title":"hello1 ","content":"hi there one!"}, {"id":2,"title":"hello 2","content":"hi there two!"} ]` w.Header().Set("content-type", "application/json") if _, err := w.Write([]byte(posts)); err != nil { panic(err) } }) m := mux.NewRouter() m.PathPrefix("/api/v1").Handler(apiRouter) m.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vmCopied := logDuration("copy vm") vm := baseVM.Copy() vmCopied() l := loop.New(vm) if err := fetch.DefineWithHandler(vm, l, apiRouter); err != nil { panic(err) } fn, err := vm.Get("renderApplication") if err != nil { panic(err) } m := map[string]interface{}{ "redirect": func(u string) { http.Redirect(w, r, u, 301) }, "error": func(e string) { http.Error(w, e, http.StatusInternalServerError) }, "notFound": func() { http.NotFound(w, r) }, "success": func(d string) { w.Header().Set("content-type", "text/html") tpl.Execute(w, map[string]string{ "html": d, }) }, } v, err := vm.ToValue(m) if err != nil { panic(err) } jsRun := logDuration("run javascript") if _, err := fn.Call(otto.UndefinedValue(), r.URL.String(), otto.NullValue(), v); err != nil { panic(err) } jsRun() jsFinished := logDuration("wait for js") if err := l.Run(); err != nil { panic(err) } jsFinished() }) n := negroni.New() n.Use(negroni.NewRecovery()) n.Use(negronilogrus.NewMiddleware()) st := negroni.NewStatic(http.Dir("../client/public")) st.IndexFile = "NOT_USED_I_HOPE" n.Use(st) n.UseHandler(m) logrus.Info("listening") if err := http.ListenAndServe(":3000", n); err != nil { panic(err) } }
func main() { logrus.StandardLogger().Level = logrus.DebugLevel logrus.Debug("starting up") baseVM := otto.New() smRead := logDuration("read sourcemap") smData, err := ioutil.ReadFile("../client/public/bundle.server.js.map") if err != nil { panic(err) } smRead() smParse := logDuration("parse sourcemap") sm, err := sourcemap.Read(bytes.NewReader(smData)) if err != nil { panic(err) } smParse() jsRead := logDuration("read javascript") jsData, err := ioutil.ReadFile("../client/public/bundle.server.js") if err != nil { panic(err) } jsRead() // lodash has a lookahead regex that we don't care about, and it makes otto // unhappy. this is a hack to get rid of it. jsData = bytes.Replace(jsData, []byte(`(?=`), []byte(`(`), -1) jsCompiled := logDuration("compile javascript") s, err := baseVM.CompileWithSourceMap("bundle.js", string(jsData), &sm) if err != nil { if st := dumpDebugError(err); st != "" { fmt.Println(st) } panic(err) } jsCompiled() jsInitialised := logDuration("initialise javascript") if _, err := baseVM.Run(s); err != nil { if st := dumpDebugError(err); st != "" { fmt.Println(st) } panic(err) } jsInitialised() vmChan := make(chan *otto.Otto) go vmCopier(baseVM, vmChan) tpl, err := template.ParseFiles("./index.template") if err != nil { panic(err) } apiRouter := mux.NewRouter() var cats = []Cat{ Cat{Name: "fluffy", FavouriteFood: "marshmallows"}, Cat{Name: "beans", FavouriteFood: "legume"}, Cat{Name: "misty", FavouriteFood: "meat"}, Cat{Name: "sara", FavouriteFood: "fish"}, } apiRouter.Path("/api/v1/cats").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("search") == "" { w.Header().Set("content-type", "application/json") if err := json.NewEncoder(w).Encode(cats); err != nil { panic(err) } return } var d []Cat for _, c := range cats { if strings.Contains(strings.ToLower(c.Name), strings.ToLower(r.URL.Query().Get("search"))) { d = append(d, c) } } w.Header().Set("content-type", "application/json") if err := json.NewEncoder(w).Encode(d); err != nil { panic(err) } }) apiRouter.Path("/api/v1/cats/{name}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) for _, c := range cats { if strings.ToLower(c.Name) == vars["name"] { w.Header().Set("content-type", "application/json") if err := json.NewEncoder(w).Encode(c); err != nil { panic(err) } return } } http.NotFound(w, r) }) m := mux.NewRouter() m.PathPrefix("/api/v1").Handler(apiRouter) m.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vmCopied := logDuration("copy vm") vm := <-vmChan vmCopied() l := loop.New(vm) if err := fetch.DefineWithHandler(vm, l, apiRouter); err != nil { panic(err) } fn, err := vm.Get("renderApplication") if err != nil { panic(err) } m := map[string]interface{}{ "redirect": func(u string) { http.Redirect(w, r, u, 301) }, "error": func(e string) { http.Error(w, e, http.StatusInternalServerError) }, "notFound": func() { http.NotFound(w, r) }, "success": func(initialState, html string) { w.Header().Set("content-type", "text/html") tpl.Execute(w, map[string]string{ "initialState": initialState, "html": html, }) }, } v, err := vm.ToValue(m) if err != nil { panic(err) } jsRun := logDuration("run javascript") if _, err := fn.Call(otto.UndefinedValue(), r.URL.String(), otto.NullValue(), v); err != nil { if st := dumpDebugError(err); st != "" { panic(fmt.Errorf("%s", st)) } panic(err) } jsRun() jsFinished := logDuration("wait for js") if err := l.Run(); err != nil { if st := dumpDebugError(err); st != "" { panic(fmt.Errorf("%s", st)) } panic(err) } jsFinished() }) n := negroni.New() n.Use(negroni.NewRecovery()) n.Use(negronilogrus.NewMiddleware()) st := negroni.NewStatic(http.Dir("../client/public")) st.IndexFile = "NOT_USED_I_HOPE" n.Use(st) n.UseHandler(m) logrus.Info("listening") if err := http.ListenAndServe(":3000", n); err != nil { panic(err) } }
func main() { flag.Parse() vm := otto.New() if *debugger { vm.SetDebuggerHandler(repl.DebuggerHandler) } l := loop.New(vm) if err := timers.Define(vm, l); err != nil { panic(err) } if err := promise.Define(vm, l); err != nil { panic(err) } if err := fetch.Define(vm, l); err != nil { panic(err) } if err := process.Define(vm, flag.Args()); err != nil { panic(err) } blockingTask := looptask.NewEvalTask("") if len(flag.Args()) == 0 || *openRepl { l.Add(blockingTask) } if len(flag.Args()) > 0 { d, err := ioutil.ReadFile(flag.Arg(0)) if err != nil { panic(err) } // this is a very cheap way of "supporting" shebang lines if d[0] == '#' { d = []byte("// " + string(d)) } s, err := vm.Compile(flag.Arg(0), string(d)) if err != nil { panic(err) } if err := l.Eval(s); err != nil { panic(err) } } if len(flag.Args()) == 0 || *openRepl { go func() { if err := erepl.Run(l); err != nil && err != io.EOF { panic(err) } l.Ready(blockingTask) }() } if err := l.Run(); err != nil { panic(err) } }