gorunwasm

command module
v0.0.0-...-730272d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2019 License: MIT Imports: 11 Imported by: 0

README

gorunwasm -- an HTTP Server Wrapper For Go

GoDoc

Demo

hello/index.html:

<!doctype html>

<title>Go WASM Hello World</title>

<body>

	<div>
		<label for="who">Who are you?</label>
		<input id="who" type="text" size="20">
	</div>

	<div id="output">...</div>

	<script src="wasm_exec.js"></script>
	<script src="index.js" data-input="#who" data-output="#output"></script>

</body>

hello/main.go:

// +build js

package main

import (
	"fmt"
	"os"
	"syscall/js"
)

var document = js.Global().Get("document")

func main() {
	input := document.Call("querySelector", os.Getenv("input"))
	output := document.Call("querySelector", os.Getenv("output"))
	input.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		val := input.Get("value")
		output.Set("innerText", fmt.Sprintf("Hello %q", val))
		return nil
	}))
	select {}
}

Then just gorunwasm within the folder containing those two files:

$ go get github.com/jcorbin/gorunwasm

$ gorunwasm
2019/05/27 19:14:53 Serving http files from "/Users/joshua/gorunwasm/hello"
2019/05/27 19:14:53 listening on http://127.0.0.1:58241

Open the browser, and type in the input:

Hello go wasm browser

But the real joy comes during development, let's break it:


diff --git a/main.go b/main.go
index 58886f6..956b143 100644
--- a/hello/main.go
+++ b/hello/main.go
@@ -24,7 +24,7 @@ func main() {
        input.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) interf
                val := input.Get("value")
                output.Set("innerText", fmt.Sprintf("Hello %q", val))
-               return nil
+               // return nil FIXME oops
        }))

        select {}

Now refresh, and see the build error

See the syscall/js package and the golang WebAssembly wiki for more.

HTML

You may write an index.html file within your main package, which will cause gorunwasm to host an http.FileServer out of the main package directory, rather than providing a static default index.html.

Any custom index.html:

  • MUST include <script src="wasm_exec.js"></script> -- hosted from $GOROOT/misc/wasm/wasm_exec.js, and is part of the upstream wasm runtime.
  • SHOULD include <script src="index.js"></script> -- is gorunwasm's runtime harness, which can be further customized with data attributes:
    • data-args provides JSON-encoded command line arguments, and causes the wasm program to be immediately ran after compilation.
    • data-argv0 provides an alternate program name to run the Go program as; the default is "PACKAGENAME.wasm".
    • data-href provides an alternate URL to the build.json config endpoint.
    • any other data attributes are passed as environment variables to the Go program; access them the normal way with os.Getenv("name")

Documentation

Overview

Package main implements the gorunwasm command, which runs an http server around a dynamic wasm building handler, along side a DOM-integrated runner script.

It hosts /wasm_exec.js as shipped with $GOROOT to implement the core Go class in the browser.

It hosts the wasm handler at /main.wasm.

It hosts a static /index.html wrapper which combines these, or an http.FileServer around the target package directory if it contains an index.html.

The runner script supports passing environment variables to the built Go wasm/js program:

<!doctype html>

<title>Go WASM Hello World</title>

<body>

	<div>
		<label for="who">Who are you?</label>
		<input id="who" type="text" size="20">
	</div>

	<div id="output">...</div>

	<script src="wasm_exec.js"></script>
	<script src="index.js" data-input="#who" data-output="#output"></script>

</body>

Which can then be used along side a corresponding main.go:

// +build js

package main

import (
	"fmt"
	"os"
	"syscall/js"
)

var document = js.Global().Get("document")

func main() {
	input := document.Call("querySelector", os.Getenv("input"))
	output := document.Call("querySelector", os.Getenv("output"))
	input.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		val := input.Get("value")
		output.Set("innerText", fmt.Sprintf("Hello %q", val))
		return nil
	}))
	select {}
}

The runner script also supports setting data-argv0 and data-args attributes to pass command line arguments. However environment variables are easier and less error prone to use, since they are simple key/value passing, where-as the args value must be a JSON encoded array of strings.

The runner script displays any text/plain content by replacing all body content with it. This aligns with WASMHandler redirecting to the build log on build failure.

Directories

Path Synopsis
Package handler implements a dynamic wasm building http.Handler.
Package handler implements a dynamic wasm building http.Handler.
Package main implements a simple hello prompter.
Package main implements a simple hello prompter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL