#include "quickjs.h"
#include "quickjs-libc.h"
#include <string>
#include <iostream>
#include "cutils.h"
JSRuntime* QJSRuntime = nullptr;
JSContext* QJSContext = nullptr;
JSContext* CreateQJSContext(JSRuntime* InRuntime)
{
JSContext* RetVal = JS_NewContext(QJSRuntime);
js_init_module_std(RetVal, "std");
js_init_module_os(RetVal, "os");
return RetVal;
}
int InitQuickJSEnv()
{
QJSRuntime = JS_NewRuntime();
js_std_set_worker_new_context_func(CreateQJSContext);
js_std_init_handlers(QJSRuntime);
QJSContext = CreateQJSContext(QJSRuntime);
JS_SetModuleLoaderFunc(QJSRuntime, nullptr, js_module_loader, nullptr);
js_std_add_helpers(QJSContext, -1, nullptr);
return 0;
}
struct MyClass
{
public:
int VoidFunc()
{
std::cout<<"CppClass:VoidFunc()"<<std::endl;
}
static JSValue JSCtor(JSContext* InCtx, JSValueConst InNewTarget, int InArgc, JSValueConst* InArgv)
{
MyClass* data = nullptr;
JSValue obj = JS_UNDEFINED;
JSValue proto;
data = (MyClass*)js_malloc(InCtx, sizeof(*data));
if (InArgc > 0)
{
JS_ToInt32(InCtx, &data->IntVal, InArgv[0]);
}
proto = JS_GetPropertyStr(InCtx, InNewTarget, "prototype");
obj = JS_NewObjectProtoClass(InCtx, proto, ClassID);
JS_FreeValue(InCtx, proto);
JS_SetOpaque(obj, data);
return obj;
}
static JSValue JSGetIntVal(JSContext* InCtx, JSValueConst InThisVal, int InMagic)
{
MyClass* data = (MyClass*)JS_GetOpaque2(InCtx, InThisVal, ClassID);
if (data == nullptr)
{
return JS_EXCEPTION;
}
return JS_NewInt32(InCtx, data->IntVal);
}
static JSValue JSSetIntVal(JSContext* InCtx, JSValueConst InThisVal, JSValue InValue, int InMagic)
{
MyClass* data = (MyClass*)JS_GetOpaque2(InCtx, InThisVal, ClassID);
if (data == nullptr)
{
return JS_EXCEPTION;
}
int v = 0;
JS_ToInt32(InCtx, &v, InValue);
data->IntVal = v;
return JS_UNDEFINED;
}
int IntVal = 0;
static JSClassID ClassID;
static JSClassDef ClassDef;
};
JSClassID MyClass::ClassID;
JSClassDef MyClass::ClassDef;
int ModuleInit(JSContext* InCtx, JSModuleDef* InModuleDef)
{
JSValue JSMyClassProto, JSMyClass;
JS_NewClassID(&MyClass::ClassID);
MyClass::ClassDef.class_name = "MyClass";
JS_NewClass(JS_GetRuntime(InCtx), MyClass::ClassID, &MyClass::ClassDef);
JSMyClassProto = JS_NewObject(InCtx);
JSCFunctionListEntry CppClassProtoFunc;
CppClassProtoFunc.name = "IntVal";
CppClassProtoFunc.prop_flags = JS_PROP_CONFIGURABLE;
CppClassProtoFunc.def_type = JS_DEF_CGETSET;
CppClassProtoFunc.magic = 0;
CppClassProtoFunc.u.getset.get.getter_magic = &MyClass::JSGetIntVal;
CppClassProtoFunc.u.getset.set.setter_magic = MyClass::JSSetIntVal;
JS_SetPropertyFunctionList(InCtx, JSMyClassProto, &CppClassProtoFunc, 1);
JSMyClass = JS_NewCFunction2(InCtx, MyClass::JSCtor, "MyClass", 1, JS_CFUNC_constructor, 0);
JS_SetConstructor(InCtx, JSMyClass, JSMyClassProto);
JS_SetClassProto(InCtx, MyClass::ClassID, JSMyClassProto);
JS_SetModuleExport(InCtx, InModuleDef, "MyClass", JSMyClass);
return 0;
}
int TestExportClassToJavaScript()
{
JSModuleDef* m;
m = JS_NewCModule(QJSContext, "CppModule", ModuleInit);
if (!m)
return -1;
JS_AddModuleExport(QJSContext, m, "MyClass");
char JSScript[] = R"(
import * as CppModule from 'CppModule';
var tmp = new CppModule.MyClass(12345);
console.log(tmp.IntVal);
tmp.IntVal = 123;
console.log(tmp.IntVal);
)";
JSValue RetValue = JS_Eval(QJSContext, JSScript, strlen(JSScript), "", JS_EVAL_TYPE_MODULE);
return 0;
}
int main(int argc, char* argv[])
{
InitQuickJSEnv();
TestExportClassToJavaScript();
js_std_dump_error(QJSContext);
system("pause");
return 0;
}
target('qjsc')
set_kind('binary')
add_defines('CONFIG_BIGNUM')
add_defines('JS_STRICT_NAN_BOXING')
add_files(
'qjsc.c',
'cutils.c',
'quickjs.c',
'quickjs-libc.c',
'libunicode.c',
'libregexp.c',
'libbf.c',
'repl.c'
)
target('qjs')
set_kind('binary')
add_defines('CONFIG_BIGNUM')
add_defines('JS_STRICT_NAN_BOXING')
add_files(
'qjs.c',
'cutils.c',
'quickjs.c',
'quickjs-libc.c',
'libunicode.c',
'libregexp.c',
'libbf.c',
'repl.c',
'qjscalc.c'
)
target('JSPointModule')
set_kind('shared')
add_defines('CONFIG_BIGNUM')
add_defines('JS_STRICT_NAN_BOXING')
add_files(
'examples/point.c',
'cutils.c',
'quickjs.c',
'quickjs-libc.c',
'libunicode.c',
'libregexp.c',
'libbf.c',
'repl.c',
'qjscalc.c'
)
target('LearnQuickJS')
set_kind('binary')
add_rules("mode.release", "mode.debug")
add_defines('CONFIG_BIGNUM')
add_defines('JS_STRICT_NAN_BOXING')
add_includedirs('./')
add_files(
'LearnQuickJS.cpp',
'cutils.c',
'quickjs.c',
'quickjs-libc.c',
'libunicode.c',
'libregexp.c',
'libbf.c'
)