Skip to content

Instantly share code, notes, and snippets.

@sangupta
Last active June 28, 2023 03:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sangupta/f08af23ce6816f7fad6ac88a267a1a6f to your computer and use it in GitHub Desktop.
Save sangupta/f08af23ce6816f7fad6ac88a267a1a6f to your computer and use it in GitHub Desktop.
Parse Typescript code in Go lang using QuickJS. The idea is to re-use the original Typescript library than rolling out a parser of our own.
package main
import (
"errors"
"fmt"
"io/ioutil"
"time"
stdruntime "runtime"
"github.com/quickjs-go/quickjs-go"
)
func check(err error) {
if err != nil {
var evalErr *quickjs.Error
if errors.As(err, &evalErr) {
fmt.Println(evalErr.Cause)
fmt.Println(evalErr.Stack)
}
panic(err)
}
}
func main() {
start := time.Now()
parse()
duration := time.Since(start)
fmt.Println(duration)
}
func parse() {
typeScript, err := ioutil.ReadFile("/path/to/typescript/lib/typescript.js")
if err != nil {
panic(err)
}
sourceCode, err := ioutil.ReadFile("/path/to/typescript/source/code/index.ts")
if err != nil {
panic(err)
}
stdruntime.LockOSThread()
runtime := quickjs.NewRuntime()
defer runtime.Free()
context := runtime.NewContext()
defer context.Free()
// load TS source code
result, err := context.EvalFile(string(typeScript), 0, "typescript.js")
check(err)
defer result.Free()
// never free this - throws cgo error at app termination
globals := context.Globals()
ts := globals.Get("ts")
defer ts.Free()
scriptTarget := ts.Get("ScriptTarget")
defer scriptTarget.Free()
system := scriptTarget.Get("Latest")
defer system.Free()
parseCode := ts.Get("createSourceFile")
defer parseCode.Free()
fmt.Println(parseCode.IsFunction())
args := make([]quickjs.Value, 4)
args[0] = context.String("index.ts")
args[1] = context.String(string(sourceCode))
args[2] = context.String("")
args[3] = context.Bool(true)
result, err = context.Call(globals, parseCode, args)
check(err)
defer result.Free()
if result.IsObject() {
names, err := result.PropertyNames()
check(err)
fmt.Println("Object:")
for _, name := range names {
val := result.GetByAtom(name.Atom)
defer val.Free()
fmt.Printf("'%s': %s\n", name, val)
}
} else {
fmt.Println(result.String())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment