summaryrefslogtreecommitdiff
path: root/javascript/dukky.h
blob: 5e81d68aed1c5701334988f55f2ddc6176bd1ab0 (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
/* DO NOT USE, DODGY BIT FOR VINCE */

#ifndef DUKKY_H
#define DUKKY_H

#include "duktape.h"

#define _MAGIC(S) ("\xFF\xFF" "NETSURF_DUKTAPE_" S)
#define MAGIC(S) _MAGIC(#S)
#define PROTO_MAGIC MAGIC(PROTOTYPES)
#define PRIVATE_MAGIC MAGIC(PRIVATE)
#define INIT_MAGIC MAGIC(INIT)
#define _PROTO_NAME(K) _MAGIC("PROTOTYPE_" K)
#define PROTO_NAME(K) _PROTO_NAME(#K)
#define _PROP_NAME(K,V) _MAGIC(K "_PROPERTY_" V)
#define PROP_NAME(K,V) _PROP_NAME(#K,#V)

#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_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_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)

#include "duktape/private.h"
#include "duktape/prototypes.h"

duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args);

#endif