mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	阶段性提交
This commit is contained in:
		
							
								
								
									
										50
									
								
								internal/js/console.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								internal/js/console.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Console struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Console) Log(args ...interface{}) {
 | 
				
			||||||
 | 
						for index, arg := range args {
 | 
				
			||||||
 | 
							if arg != nil {
 | 
				
			||||||
 | 
								switch arg.(type) {
 | 
				
			||||||
 | 
								case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, string:
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									var argType = reflect.TypeOf(arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// 是否有String()方法,如果有直接调用
 | 
				
			||||||
 | 
									method, ok := argType.MethodByName("String")
 | 
				
			||||||
 | 
									if ok && method.Type.NumIn() == 1 && method.Type.NumOut() == 1 && method.Type.Out(0).Kind() == reflect.String {
 | 
				
			||||||
 | 
										args[index] = method.Func.Call([]reflect.Value{reflect.ValueOf(arg)})[0].String()
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// 转为JSON
 | 
				
			||||||
 | 
									argJSON, err := this.toJSON(arg)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										if argType.Kind() == reflect.Func {
 | 
				
			||||||
 | 
											args[index] = "[function]"
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											args[index] = "[object]"
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										args[index] = string(argJSON)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								args[index] = "null"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logs.Println(append([]interface{}{"[js][console]"}, args...)...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Console) toJSON(o interface{}) ([]byte, error) {
 | 
				
			||||||
 | 
						return json.Marshal(o)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								internal/js/console_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								internal/js/console_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConsole_Log(t *testing.T) {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vm := NewVM()
 | 
				
			||||||
 | 
							_, err := vm.RunString("console.log('Hello', 'world')")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vm := NewVM()
 | 
				
			||||||
 | 
							_, err := vm.RunString("console.log(null, true, false, 10, 10.123)")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vm := NewVM()
 | 
				
			||||||
 | 
							_, err := vm.RunString("console.log({ a:1, b:2 })")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vm := NewVM()
 | 
				
			||||||
 | 
							_, err := vm.RunString("console.log(console.log)")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								internal/js/http.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								internal/js/http.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type HTTP struct {
 | 
				
			||||||
 | 
						r RequestInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req  *Request
 | 
				
			||||||
 | 
						resp *Response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onRequest func(req *Request, resp *Response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewHTTP(r RequestInterface) *HTTP {
 | 
				
			||||||
 | 
						return &HTTP{
 | 
				
			||||||
 | 
							req:  NewRequest(r),
 | 
				
			||||||
 | 
							resp: NewResponse(r),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *HTTP) OnRequest(callback func(req *Request, resp *Response)) {
 | 
				
			||||||
 | 
						// TODO 考虑是否支持多个callback
 | 
				
			||||||
 | 
						this.onRequest = callback
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *HTTP) OnData(callback func(req *Request, resp *Response)) {
 | 
				
			||||||
 | 
						// TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *HTTP) OnResponse(callback func(req *Request, resp *Response)) {
 | 
				
			||||||
 | 
						// TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *HTTP) TriggerRequest() {
 | 
				
			||||||
 | 
						this.onRequest(this.req, this.resp)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										82
									
								
								internal/js/request.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								internal/js/request.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Request struct {
 | 
				
			||||||
 | 
						r RequestInterface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewRequest(r RequestInterface) *Request {
 | 
				
			||||||
 | 
						return &Request{
 | 
				
			||||||
 | 
							r: r,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) Proto() string {
 | 
				
			||||||
 | 
						return this.r.JSRequest().Proto
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) Method() string {
 | 
				
			||||||
 | 
						return this.r.JSRequest().Method
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) Header() map[string][]string {
 | 
				
			||||||
 | 
						return this.r.JSRequest().Header
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) AddHeader(name string, value string) {
 | 
				
			||||||
 | 
						this.r.JSRequest().Header[name] = append(this.r.JSRequest().Header[name], value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) SetHeader(name string, value string) {
 | 
				
			||||||
 | 
						this.r.JSRequest().Header[name] = []string{value}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) RemoteAddr() string {
 | 
				
			||||||
 | 
						var remoteAddr = this.r.JSRequest().RemoteAddr
 | 
				
			||||||
 | 
						host, _, err := net.SplitHostPort(remoteAddr)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return host
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return remoteAddr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) Url() *URL {
 | 
				
			||||||
 | 
						return NewURL(this.r.JSRequest().URL)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) ContentLength() int64 {
 | 
				
			||||||
 | 
						return this.r.JSRequest().ContentLength
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) Body() []byte {
 | 
				
			||||||
 | 
						var bodyReader = this.r.JSRequest().Body
 | 
				
			||||||
 | 
						if bodyReader == nil {
 | 
				
			||||||
 | 
							return []byte{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := ioutil.ReadAll(bodyReader)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.r.JSLog("read body failed: " + err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return data
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Request) CopyBody() []byte {
 | 
				
			||||||
 | 
						var bodyReader = this.r.JSRequest().Body
 | 
				
			||||||
 | 
						if bodyReader == nil {
 | 
				
			||||||
 | 
							return []byte{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, err := ioutil.ReadAll(bodyReader)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.r.JSLog("read body failed: " + err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.r.JSRequest().Body = ioutil.NopCloser(bytes.NewReader(data))
 | 
				
			||||||
 | 
						return data
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								internal/js/request_interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								internal/js/request_interface.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RequestInterface interface {
 | 
				
			||||||
 | 
						// JSRequest 请求
 | 
				
			||||||
 | 
						JSRequest() *http.Request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// JSWriter 响应
 | 
				
			||||||
 | 
						JSWriter() http.ResponseWriter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// JSStop 中止请求
 | 
				
			||||||
 | 
						JSStop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// JSLog 打印日志
 | 
				
			||||||
 | 
						JSLog(msg ...interface{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										124
									
								
								internal/js/request_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								internal/js/request_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/js"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testRequest struct {
 | 
				
			||||||
 | 
						rawRequest  *http.Request
 | 
				
			||||||
 | 
						rawResponse *testResponse
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testRequest) JSRequest() *http.Request {
 | 
				
			||||||
 | 
						if this.rawRequest != nil {
 | 
				
			||||||
 | 
							return this.rawRequest
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req, _ := http.NewRequest(http.MethodGet, "https://iwind:123456@goedge.cn/docs?name=Libai&age=20", nil)
 | 
				
			||||||
 | 
						req.Header.Set("Server", "edgejs/1.0")
 | 
				
			||||||
 | 
						req.Header.Set("Content-Type", "application/json")
 | 
				
			||||||
 | 
						req.Body = ioutil.NopCloser(bytes.NewReader([]byte("123456")))
 | 
				
			||||||
 | 
						this.rawRequest = req
 | 
				
			||||||
 | 
						return req
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testRequest) JSWriter() http.ResponseWriter {
 | 
				
			||||||
 | 
						if this.rawResponse != nil {
 | 
				
			||||||
 | 
							return this.rawResponse
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.rawResponse = &testResponse{}
 | 
				
			||||||
 | 
						return this.rawResponse
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testRequest) JSStop() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testRequest) JSLog(msg ...interface{}) {
 | 
				
			||||||
 | 
						logs.Println(msg...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testResponse struct {
 | 
				
			||||||
 | 
						statusCode int
 | 
				
			||||||
 | 
						header     http.Header
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testResponse) Header() http.Header {
 | 
				
			||||||
 | 
						if this.header == nil {
 | 
				
			||||||
 | 
							this.header = http.Header{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return this.header
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testResponse) Write(p []byte) (int, error) {
 | 
				
			||||||
 | 
						return len(p), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *testResponse) WriteHeader(statusCode int) {
 | 
				
			||||||
 | 
						this.statusCode = statusCode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRequest(t *testing.T) {
 | 
				
			||||||
 | 
						vm := js.NewVM()
 | 
				
			||||||
 | 
						vm.SetRequest(&testRequest{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 事件监听
 | 
				
			||||||
 | 
						_, err := vm.RunString(`
 | 
				
			||||||
 | 
						http.onRequest(function (req, resp) {
 | 
				
			||||||
 | 
							console.log(req.proto())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let url = req.url()
 | 
				
			||||||
 | 
							console.log(url, "port:", url.port(), "args:", url.args())
 | 
				
			||||||
 | 
							console.log("username:", url.username(), "password:", url.password())
 | 
				
			||||||
 | 
							console.log("uri:", url.uri(), "path:", url.path())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req.addHeader("Server", "1.0")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							resp.write("this is response")
 | 
				
			||||||
 | 
							console.log(resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							console.log(req.body()) 
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 触发事件
 | 
				
			||||||
 | 
						_, err = vm.RunString(`http.triggerRequest()`)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRequest_Header(t *testing.T) {
 | 
				
			||||||
 | 
						var req = js.NewRequest(&testRequest{})
 | 
				
			||||||
 | 
						logs.PrintAsJSON(req.Header(), t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req.AddHeader("Content-Length", "10")
 | 
				
			||||||
 | 
						req.AddHeader("Vary", "1.0")
 | 
				
			||||||
 | 
						req.AddHeader("Vary", "2.0")
 | 
				
			||||||
 | 
						logs.PrintAsJSON(req.Header(), t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req.SetHeader("Vary", "3.0")
 | 
				
			||||||
 | 
						logs.PrintAsJSON(req.Header(), t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRequest_Body(t *testing.T) {
 | 
				
			||||||
 | 
						var req = js.NewRequest(&testRequest{})
 | 
				
			||||||
 | 
						t.Log(string(req.Body()))
 | 
				
			||||||
 | 
						t.Log(string(req.Body()))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRequest_CopyBody(t *testing.T) {
 | 
				
			||||||
 | 
						var req = js.NewRequest(&testRequest{})
 | 
				
			||||||
 | 
						t.Log(string(req.CopyBody()))
 | 
				
			||||||
 | 
						t.Log(string(req.CopyBody()))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								internal/js/response.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								internal/js/response.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Response struct {
 | 
				
			||||||
 | 
						r RequestInterface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewResponse(r RequestInterface) *Response {
 | 
				
			||||||
 | 
						return &Response{
 | 
				
			||||||
 | 
							r: r,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) Write(s string) error {
 | 
				
			||||||
 | 
						_, err := this.r.JSWriter().Write([]byte(s))
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) Reply(status int) {
 | 
				
			||||||
 | 
						this.SetStatus(status)
 | 
				
			||||||
 | 
						this.r.JSStop()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) Header() map[string][]string {
 | 
				
			||||||
 | 
						return this.r.JSWriter().Header()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) AddHeader(name string, value string) {
 | 
				
			||||||
 | 
						this.r.JSWriter().Header()[name] = append(this.r.JSWriter().Header()[name], value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) SetHeader(name string, value string) {
 | 
				
			||||||
 | 
						this.r.JSWriter().Header()[name] = []string{value}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Response) SetStatus(statusCode int) {
 | 
				
			||||||
 | 
						this.r.JSWriter().WriteHeader(statusCode)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								internal/js/response_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/js/response_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/js"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewResponse(t *testing.T) {
 | 
				
			||||||
 | 
						var resp = js.NewResponse(&testRequest{})
 | 
				
			||||||
 | 
						resp.AddHeader("Vary", "1.0")
 | 
				
			||||||
 | 
						resp.AddHeader("Vary", "2.0")
 | 
				
			||||||
 | 
						resp.SetHeader("Server", "edgejs/1.0")
 | 
				
			||||||
 | 
						t.Logf("%#v", resp.Header())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										90
									
								
								internal/js/url.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								internal/js/url.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/dop251/goja"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type URL struct {
 | 
				
			||||||
 | 
						u *url.URL
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewURL(u *url.URL) *URL {
 | 
				
			||||||
 | 
						return &URL{
 | 
				
			||||||
 | 
							u: u,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) JSNew(args []goja.Value) *URL {
 | 
				
			||||||
 | 
						var urlString = ""
 | 
				
			||||||
 | 
						if len(args) == 1 {
 | 
				
			||||||
 | 
							urlString = args[0].String()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						u, _ := url.Parse(urlString)
 | 
				
			||||||
 | 
						if u == nil {
 | 
				
			||||||
 | 
							u = &url.URL{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NewURL(u)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Port() int {
 | 
				
			||||||
 | 
						return types.Int(this.u.Port())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Args() map[string][]string {
 | 
				
			||||||
 | 
						return this.u.Query()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Arg(name string) string {
 | 
				
			||||||
 | 
						return this.u.Query().Get(name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Username() string {
 | 
				
			||||||
 | 
						if this.u.User != nil {
 | 
				
			||||||
 | 
							return this.u.User.Username()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Password() string {
 | 
				
			||||||
 | 
						if this.u.User != nil {
 | 
				
			||||||
 | 
							password, _ := this.u.User.Password()
 | 
				
			||||||
 | 
							return password
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Uri() string {
 | 
				
			||||||
 | 
						return this.u.RequestURI()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Path() string {
 | 
				
			||||||
 | 
						return this.u.Path
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Host() string {
 | 
				
			||||||
 | 
						return this.u.Host
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Fragment() string {
 | 
				
			||||||
 | 
						return this.u.Fragment
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Hash() string {
 | 
				
			||||||
 | 
						if len(this.u.Fragment) > 0 {
 | 
				
			||||||
 | 
							return "#" + this.u.Fragment
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) Scheme() string {
 | 
				
			||||||
 | 
						return this.u.Scheme
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *URL) String() string {
 | 
				
			||||||
 | 
						return this.u.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								internal/js/url_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								internal/js/url_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestURL(t *testing.T) {
 | 
				
			||||||
 | 
						raw, err := url.Parse("https://iwind:123456@goedge.cn/docs?name=Libai&age=20#a=b")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var u = NewURL(raw)
 | 
				
			||||||
 | 
						t.Log("host:", u.Host())
 | 
				
			||||||
 | 
						t.Log("hash:", u.Hash())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										153
									
								
								internal/js/vm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								internal/js/vm.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"github.com/dop251/goja"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sharedPrograms []*goja.Program
 | 
				
			||||||
 | 
					var sharedConsole = &Console{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						// compile programs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type VM struct {
 | 
				
			||||||
 | 
						vm *goja.Runtime
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewVM() *VM {
 | 
				
			||||||
 | 
						vm := goja.New()
 | 
				
			||||||
 | 
						vm.SetFieldNameMapper(goja.TagFieldNameMapper("json", true))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// programs
 | 
				
			||||||
 | 
						for _, program := range sharedPrograms {
 | 
				
			||||||
 | 
							_, _ = vm.RunProgram(program)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v := &VM{vm: vm}
 | 
				
			||||||
 | 
						v.initVM()
 | 
				
			||||||
 | 
						return v
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) Set(name string, obj interface{}) error {
 | 
				
			||||||
 | 
						return this.vm.Set(name, obj)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) AddConstructor(name string, instance interface{}) error {
 | 
				
			||||||
 | 
						objType := reflect.TypeOf(instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if objType.Kind() != reflect.Ptr {
 | 
				
			||||||
 | 
							return errors.New("instance should be pointer")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// construct
 | 
				
			||||||
 | 
						newMethod, ok := objType.MethodByName("JSNew")
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return errors.New("can not find 'JSNew()' method in '" + objType.Elem().Name() + "'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err = this.Set(name, func(call goja.ConstructorCall) *goja.Object {
 | 
				
			||||||
 | 
							if newMethod.Type.NumIn() != 2 {
 | 
				
			||||||
 | 
								this.throw(errors.New(objType.Elem().Name() + ".JSNew() should accept a '[]goja.Value' argument"))
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if newMethod.Type.In(1).String() != "[]goja.Value" {
 | 
				
			||||||
 | 
								this.throw(errors.New(objType.Elem().Name() + ".JSNew() should accept a '[]goja.Value' argument"))
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// new
 | 
				
			||||||
 | 
							var results = newMethod.Func.Call([]reflect.Value{reflect.ValueOf(instance), reflect.ValueOf(call.Arguments)})
 | 
				
			||||||
 | 
							if len(results) == 0 {
 | 
				
			||||||
 | 
								this.throw(errors.New(objType.Elem().Name() + ".JSNew() should return a valid instance"))
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var result = results[0]
 | 
				
			||||||
 | 
							if result.Type() != objType {
 | 
				
			||||||
 | 
								this.throw(errors.New(objType.Elem().Name() + ".JSNew() should return a same instance"))
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// methods
 | 
				
			||||||
 | 
							var resultType = result.Type()
 | 
				
			||||||
 | 
							var numMethod = result.NumMethod()
 | 
				
			||||||
 | 
							for i := 0; i < numMethod; i++ {
 | 
				
			||||||
 | 
								var method = resultType.Method(i)
 | 
				
			||||||
 | 
								var methodName = strings.ToLower(method.Name[:1]) + method.Name[1:]
 | 
				
			||||||
 | 
								err := call.This.Set(methodName, result.MethodByName(method.Name).Interface())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									this.throw(err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//  支持属性
 | 
				
			||||||
 | 
							var numField = result.Elem().Type().NumField()
 | 
				
			||||||
 | 
							for i := 0; i < numField; i++ {
 | 
				
			||||||
 | 
								var field = result.Elem().Field(i)
 | 
				
			||||||
 | 
								if !field.CanInterface() {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var fieldType = objType.Elem().Field(i)
 | 
				
			||||||
 | 
								tag, ok := fieldType.Tag.Lookup("json")
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									tag = fieldType.Name
 | 
				
			||||||
 | 
									tag = strings.ToLower(tag[:1]) + tag[1:]
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// TODO 校验tag是否符合变量语法
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								err := call.This.Set(tag, field.Interface())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									this.throw(err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) RunString(str string) (goja.Value, error) {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							e := recover()
 | 
				
			||||||
 | 
							if e != nil {
 | 
				
			||||||
 | 
								// TODO 需要打印trace
 | 
				
			||||||
 | 
								logs.Println("panic:", e)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						return this.vm.RunString(str)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) SetRequest(req RequestInterface) {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							err := this.vm.Set("http", NewHTTP(req))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								this.throw(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) initVM() {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							err := this.vm.Set("console", sharedConsole)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								this.throw(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *VM) throw(err error) {
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO
 | 
				
			||||||
 | 
						logs.Println("js:VM:error: " + err.Error())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										158
									
								
								internal/js/vm_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								internal/js/vm_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/dop251/goja"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewVM(t *testing.T) {
 | 
				
			||||||
 | 
						before := time.Now()
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vm := NewVM()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							v, err := vm.RunString("JSON.stringify({\"a\":\"b\"})")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.Log("JSON.stringify():", v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							v, err := vm.RunString(`JSON.parse('{\"a\":\"b\"}')`)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.Log("JSON.parse():", v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							err := vm.AddConstructor("Url", &URL{})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal("add constructor error:", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err = vm.RunString(`
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://goedge.cn/docs?v=1")
 | 
				
			||||||
 | 
						console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://teaos.cn/downloads?v=1")
 | 
				
			||||||
 | 
						console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url()
 | 
				
			||||||
 | 
						console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("a", "b", "c")
 | 
				
			||||||
 | 
						console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal("add constructor error:" + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestVM_Program(t *testing.T) {
 | 
				
			||||||
 | 
						var s = `
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://goedge.cn/docs?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://teaos.cn/downloads?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url()
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("a", "b", "c")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
						program := goja.MustCompile("s", s, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						before := time.Now()
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vm := NewVM()
 | 
				
			||||||
 | 
						err := vm.AddConstructor("Url", &URL{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("add constructor error:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						//_, err = vm.RunString(s)
 | 
				
			||||||
 | 
						_, err = vm.vm.RunProgram(program)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal("add constructor error:" + err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Benchmark_Program(b *testing.B) {
 | 
				
			||||||
 | 
						var s = `
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://goedge.cn/docs?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://teaos.cn/downloads?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url()
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("a", "b", "c")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://goedge.cn/docs?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("https://teaos.cn/downloads?v=1")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url()
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let u = new Url("a", "b", "c")
 | 
				
			||||||
 | 
						//console.log("host:", u.host(), u.uri())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
						program := goja.MustCompile("s", s, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vm := NewVM()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := vm.AddConstructor("Url", &URL{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							b.Fatal("add constructor error:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							//_, err = vm.RunString(s)
 | 
				
			||||||
 | 
							_, err = vm.vm.RunProgram(program)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								b.Fatal("add constructor error:" + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user