@@ -57,8 +57,17 @@ requires std::is_class_v<T>
57
57
class JSValueWrapper <T> {
58
58
public:
59
59
JSValue Wrap (JSContext* ctx, T& value) {
60
- JSValue obj = JS_NewObject (ctx);
61
- QJS_CALL (JS_SetOpaque (obj, &value));
60
+ JSClassID id = 0 ;
61
+ if constexpr (std::is_const_v<T>) {
62
+ id = QJSClass<std::remove_const_t <T>>::GetConstTypeID ();
63
+ } else {
64
+ id = QJSClass<T>::GetID ();
65
+ }
66
+ JSValue obj = JS_NewObjectClass (ctx, id);
67
+ if (JS_IsException (obj)) {
68
+ LogJSException (ctx);
69
+ }
70
+ QJS_CALL (JS_SetOpaque (obj, (void *)&value));
62
71
return obj;
63
72
}
64
73
@@ -73,7 +82,10 @@ template <typename T>
73
82
class JSValueWrapper <T*> {
74
83
public:
75
84
JSValue Wrap (JSContext* ctx, T* value) {
76
- JSValue obj = JS_NewObject (ctx);
85
+ JSValue obj = JS_NewObjectClass (ctx, QJSClass<T>::GetID ());
86
+ if (JS_IsException (obj)) {
87
+ LogJSException (ctx);
88
+ }
77
89
QJS_CALL (JS_SetOpaque (obj, value));
78
90
return obj;
79
91
}
@@ -308,14 +320,16 @@ class QJSClassBase {
308
320
virtual JSValue GetConstructor () const = 0;
309
321
virtual ~QJSClassBase () = default ;
310
322
virtual const std::string& GetName () const = 0;
323
+ virtual const std::string& GetConstName () const = 0;
311
324
};
312
325
313
326
class QJSContext {
314
327
public:
315
328
explicit QJSContext (QJSRuntime& runtime);
316
329
~QJSContext ();
317
330
318
- JSValue Eval (std::span<const char > content, const Path& filename) const ;
331
+ JSValue Eval (std::span<const char > content, const Path& filename,
332
+ bool strict_mode) const ;
319
333
320
334
QJSModule& NewModule (const std::string& name);
321
335
@@ -504,8 +518,11 @@ struct JSMemberVariableTraits {
504
518
static_assert (traits::is_member);
505
519
506
520
static JSValue Getter (JSContext* ctx, JSValue this_val, int magic) {
507
- clazz* p = static_cast <clazz*>(
508
- JS_GetOpaque2 (ctx, this_val, QJSClass<clazz>::GetID ()));
521
+ JSClassID id = JS_GetClassID (this_val);
522
+ NICKEL_ASSERT (id == QJSClass<clazz>::GetID () ||
523
+ id == QJSClass<clazz>::GetConstTypeID ());
524
+ const clazz* p = static_cast <const clazz*>(
525
+ JS_GetOpaque2 (ctx, this_val, id));
509
526
if (!p) {
510
527
LOGE (" access class variable from nullptr" );
511
528
return JS_EXCEPTION;
@@ -535,22 +552,26 @@ template <typename T>
535
552
class QJSClass : public QJSClassBase {
536
553
public:
537
554
QJSClass (QJSRuntime& runtime, const std::string& name)
538
- : m_context{runtime.GetContext ()}, m_name{name}, m_ctor{JS_UNDEFINED} {
555
+ : m_context{runtime.GetContext ()},
556
+ m_name{name},
557
+ m_const_name{" const " + name},
558
+ m_ctor{JS_UNDEFINED} {
539
559
if (id == 0 ) {
540
560
id = JS_NewClassID (runtime, &id);
541
561
}
542
562
if (const_id == 0 ) {
543
- id = JS_NewClassID (runtime, &id );
563
+ const_id = JS_NewClassID (runtime, &const_id );
544
564
}
545
565
m_def.class_name = m_name.c_str ();
546
566
m_def.finalizer = jsFinalizer;
547
567
548
- m_const_type_def.class_name = ( " const " + m_name) .c_str ();
568
+ m_const_type_def.class_name = m_const_name .c_str ();
549
569
550
570
QJS_CALL (JS_NewClass (runtime, id, &m_def));
551
571
QJS_CALL (JS_NewClass (runtime, const_id, &m_const_type_def));
552
572
553
573
m_proto = JS_NewObject (runtime.GetContext ());
574
+ m_const_type_proto = JS_NewObject (runtime.GetContext ());
554
575
}
555
576
556
577
template <typename ... Args>
@@ -581,6 +602,15 @@ class QJSClass : public QJSClassBase {
581
602
refl::list_size_v<typename traits::args>, JS_CFUNC_generic, 0 );
582
603
QJS_CALL (JS_DefinePropertyValueStr (m_context, m_proto, name.c_str (),
583
604
fn, 0 ));
605
+
606
+ if constexpr (traits::is_const) {
607
+ JSValue const_fn = JS_NewCFunction2 (
608
+ m_context, JSMemberFnTraits<F>::Fn, name.c_str (),
609
+ refl::list_size_v<typename traits::args>, JS_CFUNC_generic,
610
+ 0 );
611
+ QJS_CALL (JS_DefinePropertyValueStr (
612
+ m_context, m_const_type_proto, name.c_str (), const_fn, 0 ));
613
+ }
584
614
} else {
585
615
JSValue fn = JS_NewCFunction2 (
586
616
m_context, JSFnTraits<F>::Fn, name.c_str (),
@@ -595,18 +625,36 @@ class QJSClass : public QJSClassBase {
595
625
using traits = refl::variable_pointer_traits<F>;
596
626
static_assert (traits::is_member);
597
627
using js_traits = JSMemberVariableTraits<F>;
598
- JSCFunctionListEntry entry[] = {
599
- JS_CGETSET_MAGIC_DEF (name.c_str (), js_traits::Getter,
600
- js_traits::Setter, 0 ),
628
+
629
+ if constexpr (std::is_const_v<typename traits::type>) {
630
+ JSCFunctionListEntry entry[] = {
631
+ JS_CGETSET_MAGIC_DEF (name.c_str (), js_traits::Getter, nullptr ,
632
+ 0 ),
633
+ };
634
+ JS_SetPropertyFunctionList (m_context, m_proto, entry,
635
+ std::size (entry));
636
+ } else {
637
+ JSCFunctionListEntry entry[] = {
638
+ JS_CGETSET_MAGIC_DEF (name.c_str (), js_traits::Getter,
639
+ js_traits::Setter, 0 ),
640
+ };
641
+ JS_SetPropertyFunctionList (m_context, m_proto, entry,
642
+ std::size (entry));
643
+ }
644
+
645
+ JSCFunctionListEntry const_entry[] = {
646
+ JS_CGETSET_MAGIC_DEF (name.c_str (), js_traits::Getter, nullptr , 0 ),
601
647
};
602
- JS_SetPropertyFunctionList (m_context, m_proto, entry, std::size (entry));
648
+ JS_SetPropertyFunctionList (m_context, m_const_type_proto, const_entry,
649
+ std::size (const_entry));
603
650
return *this ;
604
651
}
605
652
606
653
template <typename U>
607
654
QJSClass& AddStaticField (const std::string& name, U* ptr) {
608
655
JS_SetPropertyStr (m_context, m_ctor, name.c_str (),
609
656
JSValueWrapper<U>{}.Wrap (m_context, *ptr));
657
+ // TODO: handle const type
610
658
return *this ;
611
659
}
612
660
@@ -619,6 +667,8 @@ class QJSClass : public QJSClassBase {
619
667
620
668
const std::string& GetName () const override { return m_name; }
621
669
670
+ const std::string& GetConstName () const override { return m_const_name; }
671
+
622
672
static JSClassID GetID () { return id; }
623
673
624
674
static JSClassID GetConstTypeID () { return const_id; }
@@ -631,6 +681,7 @@ class QJSClass : public QJSClassBase {
631
681
JSClassDef m_def{};
632
682
JSClassDef m_const_type_def{};
633
683
std::string m_name;
684
+ std::string m_const_name;
634
685
JSValue m_proto;
635
686
JSValue m_const_type_proto;
636
687
JSValue m_ctor;
0 commit comments