-
Notifications
You must be signed in to change notification settings - Fork 516
/
test-get-set-magic.c
167 lines (138 loc) · 3.95 KB
/
test-get-set-magic.c
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
* Test setting and getting the Duktape/C function magic value.
*
* The magic value is useful in sharing a single native helper
* with multiple ECMAScript bindings, with the helper's behavior
* being controlled by flags or other values in the magic value.
* The magic value is stored cheaply without needing a property
* slot.
*/
/*===
*** test_1 (duk_safe_call)
magic: 4660
magic: 4660
magic: 32767
magic: 32767
magic: -32768
magic: -32768
magic: -16657
magic: -16657
final top: 2
==> rc=0, result='undefined'
*** test_2 (duk_safe_call)
==> rc=1, result='TypeError: unexpected type'
*** test_3 (duk_safe_call)
==> rc=1, result='TypeError: nativefunction required, found [object Function] (stack index -1)'
*** test_4 (duk_safe_call)
INFO: log line<LF>
WARN: log line<LF>
ERROR: log line<CR><LF>
FATAL: log line<LF>
final top: 4
==> rc=0, result='undefined'
===*/
static duk_ret_t my_func(duk_context *ctx) {
printf("magic: %ld\n", (long) duk_get_current_magic(ctx));
return 0;
}
static duk_ret_t test_1(duk_context *ctx, void *udata) {
(void) udata;
duk_push_c_function(ctx, my_func, 0);
duk_push_undefined(ctx); /* dummy filler */
duk_set_magic(ctx, -2, 0x1234);
printf("magic: %ld\n", (long) duk_get_magic(ctx, -2));
duk_dup(ctx, -2);
duk_call(ctx, 0);
duk_pop(ctx);
duk_set_magic(ctx, -2, 0x7fff);
printf("magic: %ld\n", (long) duk_get_magic(ctx, -2));
duk_dup(ctx, -2);
duk_call(ctx, 0);
duk_pop(ctx);
duk_set_magic(ctx, -2, -0x8000);
printf("magic: %ld\n", (long) duk_get_magic(ctx, -2));
duk_dup(ctx, -2);
duk_call(ctx, 0);
duk_pop(ctx);
/* 0xdeadbeef gets truncated to 0xffffbeef == -16657 */
duk_set_magic(ctx, -2, 0xdeadbeefUL);
printf("magic: %ld\n", (long) duk_get_magic(ctx, -2));
duk_dup(ctx, -2);
duk_call(ctx, 0);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_2(duk_context *ctx, void *udata) {
(void) udata;
/* duk_get_magic() is strict: incorrect target type throws an error.
* This minimizes compiled function size and magic manipulation is
* rare.
*/
duk_eval_string(ctx, "(function () {})");
printf("magic: %ld\n", (long) duk_get_magic(ctx, -1));
return 0;
}
static duk_ret_t test_3(duk_context *ctx, void *udata) {
(void) udata;
/* duk_set_magic() is similarly strict. */
duk_eval_string(ctx, "(function () {})");
duk_set_magic(ctx, -1, 0x4321);
printf("magic: %ld\n", (long) duk_get_magic(ctx, -1));
return 0;
}
/*
* Extended version of the guide example: illustrate how a magic value can
* be used to share a single native log write helper.
*/
static duk_ret_t guide_example(duk_context *ctx) {
const char *prefix[4] = { "INFO", "WARN", "ERROR", "FATAL" };
duk_int_t magic = duk_get_current_magic(ctx);
printf("%s: %s", prefix[magic & 0x03], duk_safe_to_string(ctx, 0));
if (magic & 0x04) {
printf("<CR><LF>\n");
} else {
printf("<LF>\n");
}
return 0;
}
static duk_ret_t test_4(duk_context *ctx, void *udata) {
(void) udata;
duk_push_c_function(ctx, guide_example, 1);
duk_set_magic(ctx, -1, 0); /* INFO */
duk_push_c_function(ctx, guide_example, 1);
duk_set_magic(ctx, -1, 1); /* WARN */
duk_push_c_function(ctx, guide_example, 1);
duk_set_magic(ctx, -1, 2 | 0x04); /* ERROR */
duk_push_c_function(ctx, guide_example, 1);
duk_set_magic(ctx, -1, 3); /* FATAL */
/* 0: func with INFO level
* 1: func with WARN level
* 2: func with ERROR level and CRLF newline
* 3: func with FATAL level
*/
duk_dup(ctx, 0);
duk_push_string(ctx, "log line");
duk_call(ctx, 1);
duk_pop(ctx);
duk_dup(ctx, 1);
duk_push_string(ctx, "log line");
duk_call(ctx, 1);
duk_pop(ctx);
duk_dup(ctx, 2);
duk_push_string(ctx, "log line");
duk_call(ctx, 1);
duk_pop(ctx);
duk_dup(ctx, 3);
duk_push_string(ctx, "log line");
duk_call(ctx, 1);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_1);
TEST_SAFE_CALL(test_2);
TEST_SAFE_CALL(test_3);
TEST_SAFE_CALL(test_4);
}