mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.6 KiB
111 lines
2.6 KiB
/*
|
|
* Override functions in %NativeFunctionPrototype%. Here the example is to
|
|
* provide a name for anonymous native functions by looking up the C function
|
|
* address from a hypothetical symbol file.
|
|
*/
|
|
|
|
/*===
|
|
*** test_symbol_lookup (duk_safe_call)
|
|
foo called
|
|
bar called
|
|
RangeError: fake error from bar
|
|
at [anon] (...) internal
|
|
at myBar (...) native strict preventsyield
|
|
at myFoo (...) native strict preventsyield
|
|
at eval (...) preventsyield
|
|
final top: 1
|
|
==> rc=0, result='undefined'
|
|
===*/
|
|
|
|
static int my_foo(duk_context *ctx) {
|
|
(void) ctx;
|
|
printf("foo called\n");
|
|
duk_get_global_string(ctx, "bar");
|
|
duk_call(ctx, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int my_bar(duk_context *ctx) {
|
|
(void) ctx;
|
|
printf("bar called\n");
|
|
duk_error(ctx, DUK_ERR_RANGE_ERROR, "fake error from bar");
|
|
return 0;
|
|
}
|
|
|
|
/* Dummy symbol lookup function: map a native function pointer to a name
|
|
* (and push it) or indicate no symbol was found. An actual implementation
|
|
* might consult a flash-based symbol file, for example.
|
|
*/
|
|
static int my_symbol_lookup(duk_context *ctx, duk_c_function func) {
|
|
if (func == my_foo) {
|
|
duk_push_string(ctx, "myFoo");
|
|
return 1;
|
|
} else if (func == my_bar) {
|
|
duk_push_string(ctx, "myBar");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static duk_ret_t my_name_getter(duk_context *ctx) {
|
|
duk_c_function func;
|
|
|
|
/* this: function/lightfunc */
|
|
|
|
duk_push_this(ctx);
|
|
func = duk_get_c_function(ctx, -1);
|
|
if (func != NULL) {
|
|
if (my_symbol_lookup(ctx, func)) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* Not found, return empty string. */
|
|
duk_push_string(ctx, "");
|
|
return 1;
|
|
}
|
|
|
|
static duk_ret_t test_symbol_lookup(duk_context *ctx, void *udata) {
|
|
(void) udata;
|
|
|
|
duk_push_c_function(ctx, my_foo, 0);
|
|
duk_put_global_string(ctx, "foo");
|
|
duk_push_c_function(ctx, my_bar, 0);
|
|
duk_put_global_string(ctx, "bar");
|
|
|
|
/* The %NativeFunctionPrototype% is not directly accessible via e.g.
|
|
* the global object now, so look it up from a pushed function.
|
|
*/
|
|
duk_push_c_function(ctx, my_foo, 0);
|
|
duk_get_prototype(ctx, -1);
|
|
duk_remove(ctx, -2);
|
|
|
|
duk_push_string(ctx, "name");
|
|
duk_push_c_function(ctx, my_name_getter, 0);
|
|
|
|
/* [ %NativeFunctionPrototype% "name" my_name_getter ] */
|
|
|
|
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
|
|
duk_pop(ctx);
|
|
|
|
/* [ ] */
|
|
|
|
/* Call foo() and get a traceback. Demonstrate that the dynamically
|
|
* looked up names appear in the (censored) traceback.
|
|
*/
|
|
duk_eval_string(ctx,
|
|
"try {\n"
|
|
" foo();\n"
|
|
"} catch (e) {\n"
|
|
" var trace = e.stack;\n"
|
|
" trace = trace.replace(/\\(.*?\\)/g, '(...)');\n"
|
|
" print(trace);\n"
|
|
"}\n");
|
|
|
|
printf("final top: %ld\n", (long) duk_get_top(ctx));
|
|
return 0;
|
|
}
|
|
|
|
void test(duk_context *ctx) {
|
|
TEST_SAFE_CALL(test_symbol_lookup);
|
|
}
|
|
|