Created
June 2, 2019 06:05
-
-
Save silbinarywolf/c9109045ba84e427526f51ad3ec97a62 to your computer and use it in GitHub Desktop.
Load and run JavaScript code through ChakraCore DLL
This file contains hidden or 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" | |
"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