Beispiel #1
0
// Wrap returns a wrapper func that handles the conversion from native JavaScript *js.Object parameters
// to the following types.
//
// It supports *js.Object (left unmodified), dom.Document, dom.Element, dom.Event, dom.HTMLElement, dom.Node.
//
// For other types, the input is assumed to be a JSON string which is then unmarshalled into that type.
func Wrap(fn interface{}) func(...*js.Object) {
	v := reflect.ValueOf(fn)
	return func(args ...*js.Object) {
		in := make([]reflect.Value, v.Type().NumIn())
		for i := range in {
			switch t := v.Type().In(i); t {
			// *js.Object is passed through.
			case typeOf((**js.Object)(nil)):
				in[i] = reflect.ValueOf(args[i])

			// dom types are wrapped.
			case typeOf((*dom.Document)(nil)):
				in[i] = reflect.ValueOf(dom.WrapDocument(args[i]))
			case typeOf((*dom.Element)(nil)):
				in[i] = reflect.ValueOf(dom.WrapElement(args[i]))
			case typeOf((*dom.Event)(nil)):
				in[i] = reflect.ValueOf(dom.WrapEvent(args[i]))
			case typeOf((*dom.HTMLElement)(nil)):
				in[i] = reflect.ValueOf(dom.WrapHTMLElement(args[i]))
			case typeOf((*dom.Node)(nil)):
				in[i] = reflect.ValueOf(dom.WrapNode(args[i]))

			// Unmarshal incoming encoded JSON into the Go type.
			default:
				p := reflect.New(t)
				err := json.Unmarshal([]byte(args[i].String()), p.Interface())
				if err != nil {
					panic(err)
				}
				in[i] = reflect.Indirect(p)
			}
		}
		v.Call(in)
	}
}
Beispiel #2
0
func beginHandlerClose(ch chan error, removeHandlers func()) func(ev *js.Object) {
	return func(ev *js.Object) {
		removeHandlers()
		go func() {
			ce := dom.WrapEvent(ev).(*dom.CloseEvent)
			ch <- &closeError{CloseEvent: ce}
			close(ch)
		}()
	}
}
Beispiel #3
0
func main() {
	wsBaseURL := getWSBaseURL()

	qunit.Module("websocket.WebSocket")
	qunit.Test("Invalid URL", func(assert qunit.QUnitAssert) {
		qunit.Expect(1)

		ws, err := websocket.New("blah://blah.example/invalid")
		if err == nil {
			ws.Close()
			assert.Ok(false, "Got no error, but expected an invalid URL error")
			return
		}

		assert.Ok(true, fmt.Sprintf("Received an error: %s", err))
	})
	qunit.AsyncTest("Immediate close", func() interface{} {
		qunit.Expect(2)

		ws, err := websocket.New(wsBaseURL + "immediate-close")
		if err != nil {
			qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err))
			qunit.Start()
			return nil
		}

		ws.AddEventListener("open", false, func(ev *js.Object) {
			qunit.Ok(true, "WebSocket opened")
		})

		ws.AddEventListener("close", false, func(ev *js.Object) {
			const (
				CloseNormal            = 1000
				CloseNoReasonSpecified = 1005 // IE10 hates it when the server closes without sending a close reason
			)
			closeEvent := dom.WrapEvent(ev).(*dom.CloseEvent)
			if closeEvent.Code != CloseNormal && closeEvent.Code != CloseNoReasonSpecified {
				qunit.Ok(false, fmt.Sprintf("WebSocket close was not clean (code %d)", closeEvent.Code))
				qunit.Start()
				return
			}
			qunit.Ok(true, "WebSocket closed")
			qunit.Start()
		})

		return nil
	})

	qunit.Module("websocket.Conn")
	qunit.AsyncTest("Immediate close", func() interface{} {
		go func() {
			defer qunit.Start()

			ws, err := websocket.Dial(wsBaseURL + "immediate-close")
			if err != nil {
				qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err))
				return
			}

			qunit.Ok(true, "WebSocket opened")

			_, err = ws.Read(nil)
			if err == io.EOF {
				qunit.Ok(true, "Received EOF")
			} else if err != nil {
				qunit.Ok(false, fmt.Sprintf("Unexpected error in second read: %s", err))
			} else {
				qunit.Ok(false, "Expected EOF in second read, got no error")
			}
		}()

		return nil
	})
	qunit.AsyncTest("Failed open", func() interface{} {
		go func() {
			defer qunit.Start()

			ws, err := websocket.Dial(wsBaseURL + "404-not-found")
			if err == nil {
				ws.Close()
				qunit.Ok(false, "Got no error, but expected an error in opening the WebSocket.")
				return
			}

			qunit.Ok(true, fmt.Sprintf("WebSocket failed to open: %s", err))
		}()

		return nil
	})
	qunit.AsyncTest("Binary read", func() interface{} {
		qunit.Expect(3)

		go func() {
			defer qunit.Start()

			ws, err := websocket.Dial(wsBaseURL + "binary-static")
			if err != nil {
				qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err))
				return
			}

			qunit.Ok(true, "WebSocket opened")

			var expectedData = []byte{0x00, 0x01, 0x02, 0x03, 0x04}

			receivedData := make([]byte, len(expectedData))
			n, err := ws.Read(receivedData)
			if err != nil {
				qunit.Ok(false, fmt.Sprintf("Error in first read: %s", err))
				return
			}
			receivedData = receivedData[:n]

			if !bytes.Equal(receivedData, expectedData) {
				qunit.Ok(false, fmt.Sprintf("Received data did not match expected data. Got % x, expected % x.", receivedData, expectedData))
			} else {
				qunit.Ok(true, fmt.Sprintf("Received data: % x", receivedData))
			}

			_, err = ws.Read(receivedData)
			if err == io.EOF {
				qunit.Ok(true, "Received EOF")
			} else if err != nil {
				qunit.Ok(false, fmt.Sprintf("Unexpected error in second read: %s", err))
			} else {
				qunit.Ok(false, "Expected EOF in second read, got no error")
			}
		}()

		return nil
	})
	qunit.AsyncTest("Timeout", func() interface{} {
		qunit.Expect(2)

		go func() {
			defer qunit.Start()

			ws, err := websocket.Dial(wsBaseURL + "wait-30s")
			if err != nil {
				qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err))
				return
			}

			qunit.Ok(true, "WebSocket opened")

			start := time.Now()
			ws.SetReadDeadline(start.Add(1 * time.Second))

			_, err = ws.Read(nil)
			if err != nil && err.Error() == "i/o timeout: deadline reached" {
				totalTime := time.Now().Sub(start)
				if totalTime < 750*time.Millisecond {
					qunit.Ok(false, fmt.Sprintf("Timeout was too short: Received timeout after %s", totalTime))
					return
				}
				qunit.Ok(true, fmt.Sprintf("Received timeout after %s", totalTime))
			} else if err != nil {
				qunit.Ok(false, fmt.Sprintf("Unexpected error in read: %s", err))
			} else {
				qunit.Ok(false, "Expected timeout in read, got no error")
			}
		}()

		return nil
	})
}
Beispiel #4
0
func (c *Conn) onMessage(event *js.Object) {
	go func() {
		c.ch <- dom.WrapEvent(event).(*dom.MessageEvent)
	}()
}