Skip to content

Instantly share code, notes, and snippets.

@silbinarywolf
Created June 2, 2019 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silbinarywolf/c9109045ba84e427526f51ad3ec97a62 to your computer and use it in GitHub Desktop.
Save silbinarywolf/c9109045ba84e427526f51ad3ec97a62 to your computer and use it in GitHub Desktop.
Load and run JavaScript code through ChakraCore DLL
package main
import (
"errors"
"fmt"
"syscall"
"unsafe"
)
var (
chakraCore, _ = syscall.LoadLibrary("ChakraCore.dll")
jsCreateRuntime, _ = syscall.GetProcAddress(chakraCore, "JsCreateRuntime")
jsCreateContext, _ = syscall.GetProcAddress(chakraCore, "JsCreateContext")
jsSetCurrentContext, _ = syscall.GetProcAddress(chakraCore, "JsSetCurrentContext")
jsRunScript, _ = syscall.GetProcAddress(chakraCore, "JsRunScript")
jsConvertValueToString, _ = syscall.GetProcAddress(chakraCore, "JsConvertValueToString")
jsStringToPointer, _ = syscall.GetProcAddress(chakraCore, "JsStringToPointer")
)
const (
JsNoError = 0
JsErrorInvalidArgument = 0x10001
JsErrorNullArgument = 0x10002
JsErrorScriptCompile = 0x30002
)
const (
JsRuntimeAttributeNone = 0x00000000
)
var jsExample = `
(()=>{
return 'Hello world!';}
)()
`
func main() {
var runtime unsafe.Pointer
var context unsafe.Pointer
var jsResult unsafe.Pointer
var resultJSString unsafe.Pointer
{
const functionName = "JsCreateRuntime"
ret, _, err := syscall.Syscall(
uintptr(jsCreateRuntime),
3,
uintptr(JsRuntimeAttributeNone),
uintptr(0),
uintptr(unsafe.Pointer(&runtime)),
)
// NOTE: Skip this error as it seems to be a false positive
//if err != 0 {
// panic(fmt.Sprintf("%s invalid DLL call: %v", functionName, err))
//}
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
if runtime == nil {
panic("Runtime should not be 0. I think.")
}
fmt.Print(fmt.Sprintf("%s: runtime: %v | error code: %v | dll call error: %v\n", functionName, runtime, ret, err))
}
{
const functionName = "JsCreateContext"
ret, _, err := syscall.Syscall(
uintptr(jsCreateContext),
2,
uintptr(runtime),
uintptr(unsafe.Pointer(&context)),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: context: %v | error code: %v | dll call error: %v\n", functionName, context, ret, err))
}
{
const functionName = "JsSetCurrentContext"
ret, _, err := syscall.Syscall(
uintptr(jsSetCurrentContext),
1,
uintptr(context),
uintptr(0),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: error code: %v | dll call error: %v\n", functionName, ret, err))
}
{
const functionName = "JsRunScript"
context := 1
str, err := syscall.UTF16PtrFromString(jsExample)
if err != nil {
panic(err)
}
url, err := syscall.UTF16PtrFromString("")
if err != nil {
panic(err)
}
ret, _, err := syscall.Syscall6(
uintptr(jsRunScript),
4,
uintptr(unsafe.Pointer(str)),
uintptr(context),
uintptr(unsafe.Pointer(url)),
uintptr(unsafe.Pointer(&jsResult)),
uintptr(0),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: js result: %v | error code: %v | dll call error: %v\n", functionName, jsResult, ret, err))
}
{
const functionName = "JsConvertValueToString"
ret, _, err := syscall.Syscall(
uintptr(jsConvertValueToString),
2,
uintptr(jsResult),
uintptr(unsafe.Pointer(&resultJSString)),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: js convert val to string: %v | error code: %v | dll call error: %v\n", functionName, resultJSString, ret, err))
}
{
const functionName = "JsStringToPointer"
var utf16StringData *[0xffff]uint16
var stringLen uintptr
ret, _, err := syscall.Syscall(
uintptr(jsStringToPointer),
3,
uintptr(resultJSString),
uintptr(unsafe.Pointer(&utf16StringData)),
uintptr(unsafe.Pointer(&stringLen)),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
cStrData := syscall.UTF16ToString(utf16StringData[0 : stringLen])
fmt.Print(fmt.Sprintf("%s: js string: %s (len: %v) | error code: %v | dll call error: %v\n", functionName, cStrData, stringLen, ret, err))
}
return
}
func getJSError(errorCode uintptr) error {
switch (errorCode) {
case JsNoError:
return nil
case JsErrorInvalidArgument:
return errors.New("An argument to a hosting API was invalid. (JsErrorInvalidArgument)")
case JsErrorNullArgument:
return errors.New("An argument to a hosting API was null in a context where null is not allowed. (JsErrorNullArgument)")
case JsErrorScriptCompile:
return errors.New("JavaScript failed to compile. (JsErrorScriptCompile)")
default:
return fmt.Errorf("Unhandled error kind (%v).", errorCode)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment