summaryrefslogtreecommitdiff
path: root/javascript/dukky.h
blob: acc65af2d6318cd3e4daf0c73635374d1ae9445c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* DO NOT USE, DODGY BIT FOR VINCE */

#ifndef DUKKY_H
#define DUKKY_H


#define DUKKY_FUNC_T(t,e) dukky_##t##_##e
#define DUKKY_FUNC(t,e) duk_ret_t DUKKY_FUNC_T(t,e) (duk_context *ctx)

static inline void *dukky_get_private(duk_context *ctx, int idx)
{
	void *ret;
	duk_get_prop_string(ctx, idx, PRIVATE_MAGIC);
	ret = duk_get_pointer(ctx, -1);
	duk_pop(ctx);
	return ret;
}

#define DUKKY_CREATE_PRIVATE(klass)		\
	klass##_private_t *priv = calloc(1, sizeof(*priv));	\
	if (priv == NULL) return 0;				\
	duk_push_pointer(ctx, priv);				\
	duk_put_prop_string(ctx, 0, PRIVATE_MAGIC)

#define DUKKY_SET_DESTRUCTOR(idx,n)		\
	duk_dup(ctx, idx);						\
	duk_push_c_function(ctx, DUKKY_FUNC_T(n,__destructor), 1);	\
	duk_set_finalizer(ctx, -2);		\
	duk_pop(ctx);

#define DUKKY_SET_CONSTRUCTOR(idx,n,a)			\
	duk_dup(ctx, idx);			\
	duk_push_c_function(ctx, DUKKY_FUNC_T(n,__constructor), 1 + a);	\
	duk_put_prop_string(ctx, -2, INIT_MAGIC);	\
	duk_pop(ctx);

#define DUKKY_SAFE_GET_PRIVATE(t,idx)		\
	t##_private_t *priv = dukky_get_private(ctx, idx);	\
	if (priv == NULL) return 0; /* No can do */

#define DUKKY_SAFE_GET_ANOTHER(n,t,idx)				\
	t##_private_t *n = dukky_get_private(ctx, idx);	\
	if (priv == NULL) return 0; /* No can do */

#define DUKKY_GET_METHOD_PRIVATE(t)		\
	t##_private_t *priv = NULL;			\
	duk_push_this(ctx);				\
	duk_get_prop_string(ctx, -1, PRIVATE_MAGIC);	\
	priv = duk_get_pointer(ctx, -1);		\
	duk_pop_2(ctx);					\
	if (priv == NULL) return 0; /* No can do */

#define DUKKY_GET_PROTOTYPE(klass)			\
	duk_get_global_string(ctx, PROTO_MAGIC);	\
	duk_get_prop_string(ctx, -1, PROTO_NAME(klass));	\
	duk_replace(ctx, -2)

#define DUKKY_DECLARE_PROTOTYPE(klass)		\
	DUKKY_FUNC(klass,__proto)

#define DUKKY_GETTER(klass,prop)		\
	duk_ret_t DUKKY_FUNC_T(klass,prop##_getter)(duk_context *ctx)

#define DUKKY_SETTER(klass,prop)		\
	duk_ret_t DUKKY_FUNC_T(klass,prop##_setter)(duk_context *ctx)

#define DUKKY_POPULATE_FULL_PROPERTY(klass,prop)	\
	duk_dup(ctx, 0);			\
	duk_push_string(ctx, #prop);		\
	duk_push_c_function(ctx, DUKKY_FUNC_T(klass,prop##_getter), 0); \
	duk_push_c_function(ctx, DUKKY_FUNC_T(klass,prop##_setter), 1); \
	duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |			\
		     DUK_DEFPROP_HAVE_SETTER |				\
		     DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE | \
		     DUK_DEFPROP_HAVE_CONFIGURABLE);			\
	duk_pop(ctx)

#define DUKKY_POPULATE_READONLY_PROPERTY(klass,prop)	\
	duk_dup(ctx, 0);			\
	duk_push_string(ctx, #prop);		\
	duk_push_c_function(ctx, DUKKY_FUNC_T(klass,prop##_getter), 0); \
	duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER |			\
		     DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE | \
		     DUK_DEFPROP_HAVE_CONFIGURABLE);			\
	duk_pop(ctx)

#define DUKKY_DUMP_STACK(ctx)				\
	do {						\
		duk_push_context_dump(ctx);		\
		LOG("Stack: %s", duk_to_string(ctx, -1));	\
		duk_pop(ctx);					\
	} while(0)

#define DUKKY_ADD_METHOD(klass,meth,nargs)	\
	duk_dup(ctx, 0);			\
	duk_push_string(ctx, #meth);		\
	duk_push_c_function(ctx, DUKKY_FUNC_T(klass,meth), nargs);	\
	DUKKY_DUMP_STACK(ctx);\
	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |			\
		     DUK_DEFPROP_HAVE_WRITABLE |			\
		     DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE | \
		     DUK_DEFPROP_HAVE_CONFIGURABLE);			\
	duk_pop(ctx)

#define DUKKY_FUNC_INIT(klass,args...)	\
	void DUKKY_FUNC_T(klass, __init)(duk_context *ctx, klass##_private_t *priv, ##args)

#define DUKKY_FUNC_FINI(klass)			\
	void DUKKY_FUNC_T(klass, __fini)(duk_context *ctx, klass##_private_t *priv)

#define DUKKY_DECLARE_INTERFACE(klass,init...)		\
	DUKKY_FUNC(klass, __proto);			\
	DUKKY_FUNC_INIT(klass, ##init);	\
	DUKKY_FUNC_FINI(klass)


duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args);
duk_bool_t dukky_push_node_stacked(duk_context *ctx);
duk_bool_t dukky_push_node(duk_context *ctx, struct dom_node *node);


#endif