Skip to content

Commit 7431cc6

Browse files
Merge pull request #3 from puerts/dev
合入Dev
2 parents dbf7efd + 640e4a9 commit 7431cc6

6 files changed

Lines changed: 197 additions & 22 deletions

File tree

CMakeLists.txt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ if(MSVC)
6868
xcheck_add_c_compiler_flag(/wd4996) # -Wdeprecated-declarations
6969
xcheck_add_c_compiler_flag(/wd5045) # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
7070
xcheck_add_c_compiler_flag(/wd4514)
71-
xcheck_add_c_compiler_flag(/wd4514)
71+
xcheck_add_c_compiler_flag(/wd4146)
72+
xcheck_add_c_compiler_flag(/wd4334)
7273
xcheck_add_c_compiler_flag(-fchar8_t)
7374
xcheck_add_c_compiler_flag(/Zc:char8_t)
7475
endif()
@@ -193,15 +194,10 @@ target_compile_options(PapiQjs PRIVATE
193194
-fno-rtti
194195
>
195196
$<$<CXX_COMPILER_ID:MSVC>:
196-
/EHa-
197-
/EHsc
198-
/EHsc-
199-
/GR- # 禁用RTTI
197+
/EHa- # 禁用异常处理
198+
/GR- # 禁用RTTI
200199
>
201200
)
202-
#if(MSVC)
203-
#target_compile_options(PapiQjs PRIVATE /EHsc)
204-
#endif()
205201

206202
target_compile_definitions(PapiRegister PUBLIC BUILDING_REGISTER_API_SHARED)
207203
target_compile_options(PapiRegister PRIVATE
@@ -213,7 +209,6 @@ target_compile_options(PapiRegister PRIVATE
213209
>
214210
$<$<CXX_COMPILER_ID:MSVC>:
215211
/EHa-
216-
/EHsc-
217212
/GR- # 禁用RTTI
218213
>
219214
)

quickjs/quickjs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55893,4 +55893,13 @@ JS_BOOL JS_GetArrayBufferViewInfo(JSContext *ctx, JSValueConst obj,
5589355893
return TRUE;
5589455894
}
5589555895

55896+
int JS_ValueRefCount(JSContext *ctx, JSValue v)
55897+
{
55898+
if (JS_VALUE_HAS_REF_COUNT(v)) {
55899+
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
55900+
return p->ref_count;
55901+
}
55902+
return -1;
55903+
}
55904+
5589655905
/*-------end additional function---------*/

quickjs/quickjs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,8 @@ JS_BOOL JS_GetArrayBufferViewInfo(JSContext *ctx, JSValueConst obj,
10491049
size_t *pbyte_length,
10501050
size_t *pbytes_per_element);
10511051

1052+
int JS_ValueRefCount(JSContext *ctx, JSValue v);
1053+
10521054
/*-------end additional function---------*/
10531055

10541056
#ifdef __cplusplus

source/CppObjectMapper.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ JSValue CppObjectMapper::CreateClass(const puerts::JSClassDefinition* ClassDefin
251251
{
252252
return JS_Throw(ctx, CppObjectMapper::CreateError(ctx, "no initialize function"));
253253
}
254-
}, 0, 0, 3, &ctor_data[0]);
254+
}, 0, 0, 3, &ctor_data[0]); // ref_count: 1
255255

256256
JS_SetConstructorBit(ctx, func, 1);
257257

@@ -295,11 +295,22 @@ JSValue CppObjectMapper::CreateClass(const puerts::JSClassDefinition* ClassDefin
295295
++FunctionInfo;
296296
}
297297

298-
JS_SetConstructor(ctx, func, proto);
298+
JS_SetConstructor(ctx, func, proto); // func ref_count: 2
299299
JS_FreeValue(ctx, proto);
300300

301+
if (ClassDefinition->SuperTypeId)
302+
{
303+
if (auto SuperDefinition = puerts::FindClassByID(ClassDefinition->SuperTypeId))
304+
{
305+
JSValue super_func = CreateClass(SuperDefinition);
306+
JSValue parent_proto = JS_GetProperty(ctx, super_func, JS_ATOM_prototype);
307+
JS_SetPrototype(ctx, proto, parent_proto);
308+
JS_FreeValue(ctx, parent_proto);
309+
}
310+
}
311+
301312
TypeIdToFunctionMap[ClassDefinition->TypeId] = func;
302-
JS_DupValue(ctx, func); //JS_FreeValue in Cleanup
313+
//printf("register class %s, tid:%p, rc:%d, obj:%p\n", ClassDefinition->ScriptName, ClassDefinition->TypeId, JS_ValueRefCount(ctx, func), JS_VALUE_GET_PTR(func));
303314
return func;
304315
}
305316
return it->second;

source/PapiQuickjsImpl.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ pesapi_value pesapi_create_class(pesapi_env env, const void* type_id)
197197
auto ctx = qjsContextFromPesapiEnv(env);
198198
auto ret = allocValueInCurrentScope(ctx);
199199
*ret = pesapi::qjsimpl::CppObjectMapper::Get(ctx)->CreateClassByID(type_id);
200+
JS_DupValue(ctx, *ret);
200201
return pesapiValueFromQjsValue(ret);
201202
}
202203

@@ -471,7 +472,7 @@ pesapi_value pesapi_get_arg(pesapi_callback_info pinfo, int index)
471472
}
472473
}
473474

474-
PESAPI_EXTERN pesapi_env pesapi_get_env(pesapi_callback_info pinfo)
475+
pesapi_env pesapi_get_env(pesapi_callback_info pinfo)
475476
{
476477
return pesapiEnvFromQjsContext(pinfo->ctx);
477478
}
@@ -623,7 +624,13 @@ void pesapi_close_scope_placement(pesapi_scope scope)
623624

624625
pesapi_value_ref pesapi_create_value_ref(pesapi_env env, pesapi_value pvalue, uint32_t internal_field_count)
625626
{
626-
return {};
627+
auto ctx = qjsContextFromPesapiEnv(env);
628+
size_t totalSize = sizeof(pesapi_value_ref__) + sizeof(void*) * internal_field_count;
629+
auto ret = (pesapi_value_ref)malloc(totalSize);
630+
memset(ret, 0, totalSize);
631+
JSValue* v = qjsValueFromPesapiValue(pvalue);
632+
new (ret) pesapi_value_ref__(ctx, *v, internal_field_count);
633+
return ret;
627634
}
628635

629636
pesapi_value_ref pesapi_duplicate_value_ref(pesapi_value_ref value_ref)
@@ -646,16 +653,31 @@ void pesapi_release_value_ref(pesapi_value_ref value_ref)
646653

647654
pesapi_value pesapi_get_value_from_ref(pesapi_env env, pesapi_value_ref value_ref)
648655
{
649-
return {};
656+
auto ctx = qjsContextFromPesapiEnv(env);
657+
JSValue* v = allocValueInCurrentScope(ctx);
658+
*v = JS_DupValue(ctx, value_ref->value_persistent);
659+
return pesapiValueFromQjsValue(v);
650660
}
651661

652662
void pesapi_set_ref_weak(pesapi_env env, pesapi_value_ref value_ref)
653663
{
664+
auto ctx = qjsContextFromPesapiEnv(env);
665+
JS_FreeValue(ctx, value_ref->value_persistent);
654666
}
655667

656668
bool pesapi_set_owner(pesapi_env env, pesapi_value pvalue, pesapi_value powner)
657669
{
658-
return false;
670+
auto ctx = qjsContextFromPesapiEnv(env);
671+
JSValue* obj = qjsValueFromPesapiValue(pvalue);
672+
JSValue* owner = qjsValueFromPesapiValue(powner);
673+
if (JS_IsObject(*owner))
674+
{
675+
JSAtom key = JS_NewAtom(ctx, "_p_i_only_one_child");
676+
JS_DupValue(ctx, *obj);
677+
JS_SetProperty(ctx, *owner, key, *obj);
678+
JS_FreeAtom(ctx, key);
679+
}
680+
return true;
659681
}
660682

661683
pesapi_env_ref pesapi_get_ref_associated_env(pesapi_value_ref value_ref)
@@ -665,7 +687,8 @@ pesapi_env_ref pesapi_get_ref_associated_env(pesapi_value_ref value_ref)
665687

666688
void** pesapi_get_ref_internal_fields(pesapi_value_ref value_ref, uint32_t* pinternal_field_count)
667689
{
668-
return {};
690+
*pinternal_field_count = value_ref->internal_field_count;
691+
return &value_ref->internal_fields[0];
669692
}
670693

671694
pesapi_value pesapi_get_property(pesapi_env env, pesapi_value pobject, const char* key)
@@ -726,7 +749,16 @@ void pesapi_set_property_uint32(pesapi_env env, pesapi_value pobject, uint32_t k
726749

727750
pesapi_value pesapi_call_function(pesapi_env env, pesapi_value pfunc, pesapi_value this_object, int argc, const pesapi_value argv[])
728751
{
729-
return {};
752+
auto ctx = qjsContextFromPesapiEnv(env);
753+
JSValue* func = qjsValueFromPesapiValue(pfunc);
754+
JSValue* thisObj = this_object ? qjsValueFromPesapiValue(this_object) : &literal_values_undefined;
755+
JSValue *js_argv = (JSValue*)alloca(argc * sizeof(JSValue));
756+
for (int i = 0; i < argc; ++i) {
757+
js_argv[i] = *qjsValueFromPesapiValue(argv[i]);
758+
}
759+
JSValue* ret = allocValueInCurrentScope(ctx);
760+
*ret = JS_Call(ctx, *func, *thisObj, argc, js_argv);
761+
return pesapiValueFromQjsValue(ret);
730762
}
731763

732764
pesapi_value pesapi_eval(pesapi_env env, const uint8_t* code, size_t code_size, const char* path)

test/papi_qjs_base_test.cpp

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,24 @@
77
namespace pesapi {
88
namespace qjsimpl {
99

10-
struct TestStruct {
10+
struct TestStructBase {
11+
TestStructBase(int b) {
12+
this->b = b;
13+
}
14+
15+
int b;
16+
int Foo(int a)
17+
{
18+
return a + b;
19+
}
20+
};
21+
22+
struct TestStruct : public TestStructBase {
1123
static int ctor_count;
1224
static int dtor_count;
1325
static TestStruct* lastCtorObject;
1426
static TestStruct* lastDtorObject;
15-
TestStruct(int a) {
27+
TestStruct(int a) : TestStructBase(a - 1) {
1628
this->a = a;
1729
ctor_count++;
1830
lastCtorObject = this;
@@ -37,6 +49,8 @@ struct TestStruct {
3749
}
3850
};
3951

52+
const void* baseTypeId = "TestStructBase";
53+
4054
const void* typeId = "TestStruct";
4155

4256
int TestStruct::ctor_count = 0;
@@ -57,6 +71,33 @@ static void TestStructFinalize(struct pesapi_ffi* apis, void* ptr, void* class_d
5771
delete (TestStruct*)ptr;
5872
}
5973

74+
static void BGetterWrap(struct pesapi_ffi* apis, pesapi_callback_info info)
75+
{
76+
auto env = apis->get_env(info);
77+
auto self = apis->get_this(info);
78+
auto obj = (TestStructBase*)apis->get_native_object_ptr(env, self);
79+
apis->add_return(info, apis->create_int32(env, obj->b));
80+
}
81+
82+
static void BSetterWrap(struct pesapi_ffi* apis, pesapi_callback_info info)
83+
{
84+
auto env = apis->get_env(info);
85+
auto self = apis->get_this(info);
86+
auto obj = (TestStructBase*)apis->get_native_object_ptr(env, self);
87+
auto p0 = apis->get_arg(info, 0);
88+
obj->b = apis->get_value_int32(env, p0);
89+
}
90+
91+
static void BaseFooWrap(struct pesapi_ffi* apis, pesapi_callback_info info)
92+
{
93+
auto env = apis->get_env(info);
94+
auto self = apis->get_this(info);
95+
auto obj = (TestStructBase*)apis->get_native_object_ptr(env, self);
96+
auto p0 = apis->get_arg(info, 0);
97+
int a = apis->get_value_int32(env, p0);
98+
apis->add_return(info, apis->create_int32(env, obj->Foo(a)));
99+
}
100+
60101
static void AddWrap(struct pesapi_ffi* apis, pesapi_callback_info info)
61102
{
62103
auto env = apis->get_env(info);
@@ -131,7 +172,25 @@ static void IncWrap(struct pesapi_ffi* apis, pesapi_callback_info info)
131172

132173
class PApiBaseTest : public ::testing::Test {
133174
public:
134-
static void SetUpTestCase() {
175+
static void SetUpTestCase() {
176+
// 封装TestStructBase
177+
const int base_properties_count = 2;
178+
pesapi_property_descriptor base_properties = pesapi_alloc_property_descriptors(base_properties_count);
179+
pesapi_set_property_info(base_properties, 0, "b", false, BGetterWrap, BSetterWrap, NULL, NULL, NULL);
180+
pesapi_set_method_info(base_properties, 1, "Foo", false, BaseFooWrap, NULL, NULL);
181+
pesapi_define_class(baseTypeId, NULL, "TestStructBase",
182+
[](struct pesapi_ffi* apis, pesapi_callback_info info) -> void* { // Ctor
183+
auto env = apis->get_env(info);
184+
auto p0 = apis->get_arg(info, 0);
185+
int b = apis->get_value_int32(env, p0);
186+
return new TestStructBase(b);
187+
},
188+
[](struct pesapi_ffi* apis, void* ptr, void* class_data, void* env_private) { // Finalize
189+
delete static_cast<TestStructBase*>(ptr);
190+
},
191+
base_properties_count, base_properties, NULL);
192+
193+
// 封装TestStruct
135194
const int properties_count = 6;
136195
pesapi_property_descriptor properties = pesapi_alloc_property_descriptors(properties_count);
137196
pesapi_set_method_info(properties, 0, "Add", true, AddWrap, NULL, NULL);
@@ -140,7 +199,7 @@ class PApiBaseTest : public ::testing::Test {
140199
pesapi_set_property_info(properties, 3, "ctor_count", true, CtorCountGetterWrap, CtorCountSetterWrap, NULL, NULL, NULL);
141200
pesapi_set_method_info(properties, 4, "GetSelf", false, GetSelfWrap, NULL, NULL);
142201
pesapi_set_method_info(properties, 5, "Inc", false, IncWrap, NULL, NULL);
143-
pesapi_define_class(typeId, NULL, "TestStruct", TestStructCtor, TestStructFinalize, properties_count, properties, NULL);
202+
pesapi_define_class(typeId, baseTypeId, "TestStruct", TestStructCtor, TestStructFinalize, properties_count, properties, NULL);
144203
}
145204

146205
static void TearDownTestCase() {
@@ -473,6 +532,26 @@ TEST_F(PApiBaseTest, ReturnAObject) {
473532
ASSERT_TRUE(apis->get_value_bool(env, ret));
474533
}
475534

535+
TEST_F(PApiBaseTest, MutiObject) {
536+
auto env = apis->get_env_from_ref(env_ref);
537+
538+
auto code = R"(
539+
(function() {
540+
const TestStruct = loadClass('TestStruct');
541+
for (let i = 0; i < 1000; ++i) {
542+
const obj = new TestStruct(123);
543+
const self = obj.GetSelf();
544+
}
545+
})();
546+
)";
547+
auto ret = apis->eval(env, (const uint8_t*)(code), strlen(code), "test.js");
548+
if (apis->has_caught(scope))
549+
{
550+
printf("%s\n", apis->get_exception_as_string(scope, true));
551+
}
552+
ASSERT_FALSE(apis->has_caught(scope));
553+
}
554+
476555
TEST_F(PApiBaseTest, RefArgument) {
477556
auto env = apis->get_env_from_ref(env_ref);
478557

@@ -495,6 +574,53 @@ TEST_F(PApiBaseTest, RefArgument) {
495574
EXPECT_EQ(5, apis->get_value_int32(env, ret));
496575
}
497576

577+
TEST_F(PApiBaseTest, CallFunction) {
578+
auto env = apis->get_env_from_ref(env_ref);
579+
580+
auto code = R"(
581+
function sub(x, y) {
582+
return x - y;
583+
}
584+
sub;
585+
)";
586+
auto ret = apis->eval(env, (const uint8_t*)(code), strlen(code), "test.js");
587+
if (apis->has_caught(scope))
588+
{
589+
printf("%s\n", apis->get_exception_as_string(scope, true));
590+
}
591+
ASSERT_FALSE(apis->has_caught(scope));
592+
ASSERT_TRUE(apis->is_function(env, ret));
593+
pesapi_value argv[2] {apis->create_int32(env, 5), apis->create_int32(env, 3)};
594+
auto func_call_ret = apis->call_function(env, ret, nullptr, 2, argv);
595+
ASSERT_TRUE(apis->is_int32(env, func_call_ret));
596+
EXPECT_EQ(2, apis->get_value_int32(env, func_call_ret));
597+
}
598+
599+
TEST_F(PApiBaseTest, SuperAccess) {
600+
auto env = apis->get_env_from_ref(env_ref);
601+
602+
auto code = R"(
603+
(function() {
604+
const TestStruct = loadClass('TestStruct');
605+
const obj = new TestStruct(123);
606+
let ret = "" + obj.b + ":"; // 122
607+
obj.b = 5
608+
ret += obj.Foo(6); // 11
609+
return ret;
610+
})();
611+
)";
612+
auto ret = apis->eval(env, (const uint8_t*)(code), strlen(code), "test.js");
613+
if (apis->has_caught(scope))
614+
{
615+
printf("%s\n", apis->get_exception_as_string(scope, true));
616+
}
617+
ASSERT_FALSE(apis->has_caught(scope));
618+
ASSERT_TRUE(apis->is_string(env, ret));
619+
char buff[1024];
620+
size_t len = sizeof(buff);
621+
const char* str = apis->get_value_string_utf8(env, ret, buff, &len);
622+
EXPECT_STREQ("122:11", str);
623+
}
498624

499625
} // namespace qjsimpl
500626
} // namespace pesapi

0 commit comments

Comments
 (0)