Last active
June 28, 2023 03:54
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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