diff options
Diffstat (limited to 'vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c')
-rwxr-xr-x | vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c b/vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c new file mode 100755 index 000000000..9a29903cf --- /dev/null +++ b/vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c @@ -0,0 +1,163 @@ +/* + * Minimal 'console' binding. + * + * https://github.com/DeveloperToolsWG/console-object/blob/master/api.md + * https://developers.google.com/web/tools/chrome-devtools/debug/console/console-reference + * https://developer.mozilla.org/en/docs/Web/API/console + */ + +#include <stdio.h> +#include <stdarg.h> +#include "duktape.h" +#include "duk_console.h" + +/* XXX: Add some form of log level filtering. */ + +/* XXX: For now logs everything to stdout, V8/Node.js logs debug/info level + * to stdout, warn and above to stderr. Should this extra do the same? + */ + +/* XXX: Should all output be written via e.g. console.write(formattedMsg)? + * This would make it easier for user code to redirect all console output + * to a custom backend. + */ + +/* XXX: Init console object using duk_def_prop() when that call is available. */ + +static duk_ret_t duk__console_log_helper(duk_context *ctx, const char *error_name) { + duk_idx_t i, n; + duk_uint_t flags; + + flags = (duk_uint_t) duk_get_current_magic(ctx); + + n = duk_get_top(ctx); + + duk_get_global_string(ctx, "console"); + duk_get_prop_string(ctx, -1, "format"); + + for (i = 0; i < n; i++) { + if (duk_check_type_mask(ctx, i, DUK_TYPE_MASK_OBJECT)) { + /* Slow path formatting. */ + duk_dup(ctx, -1); /* console.format */ + duk_dup(ctx, i); + duk_call(ctx, 1); + duk_replace(ctx, i); /* arg[i] = console.format(arg[i]); */ + } + } + + duk_pop_2(ctx); + + duk_push_string(ctx, " "); + duk_insert(ctx, 0); + duk_join(ctx, n); + + if (error_name) { + duk_push_error_object(ctx, DUK_ERR_ERROR, "%s", duk_require_string(ctx, -1)); + duk_push_string(ctx, "name"); + duk_push_string(ctx, error_name); + duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE); /* to get e.g. 'Trace: 1 2 3' */ + duk_get_prop_string(ctx, -1, "stack"); + } + + fprintf(stdout, "%s\n", duk_to_string(ctx, -1)); + if (flags & DUK_CONSOLE_FLUSH) { + fflush(stdout); + } + return 0; +} + +static duk_ret_t duk__console_assert(duk_context *ctx) { + if (duk_to_boolean(ctx, 0)) { + return 0; + } + duk_remove(ctx, 0); + + return duk__console_log_helper(ctx, "AssertionError"); +} + +static duk_ret_t duk__console_log(duk_context *ctx) { + return duk__console_log_helper(ctx, NULL); +} + +static duk_ret_t duk__console_trace(duk_context *ctx) { + return duk__console_log_helper(ctx, "Trace"); +} + +static duk_ret_t duk__console_info(duk_context *ctx) { + return duk__console_log_helper(ctx, NULL); +} + +static duk_ret_t duk__console_warn(duk_context *ctx) { + return duk__console_log_helper(ctx, NULL); +} + +static duk_ret_t duk__console_error(duk_context *ctx) { + return duk__console_log_helper(ctx, "Error"); +} + +static duk_ret_t duk__console_dir(duk_context *ctx) { + /* For now, just share the formatting of .log() */ + return duk__console_log_helper(ctx, 0); +} + +static void duk__console_reg_vararg_func(duk_context *ctx, duk_c_function func, const char *name, duk_uint_t flags) { + duk_push_c_function(ctx, func, DUK_VARARGS); + duk_push_string(ctx, "name"); + duk_push_string(ctx, name); + duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE); /* Improve stacktraces by displaying function name */ + duk_set_magic(ctx, -1, (duk_int_t) flags); + duk_put_prop_string(ctx, -2, name); +} + +void duk_console_init(duk_context *ctx, duk_uint_t flags) { + duk_push_object(ctx); + + /* Custom function to format objects; user can replace. + * For now, try JX-formatting and if that fails, fall back + * to ToString(v). + */ + duk_eval_string(ctx, + "(function (E) {" + "return function format(v){" + "try{" + "return E('jx',v);" + "}catch(e){" + "return String(v);" /* String() allows symbols, ToString() internal algorithm doesn't. */ + "}" + "};" + "})(Duktape.enc)"); + duk_put_prop_string(ctx, -2, "format"); + + duk__console_reg_vararg_func(ctx, duk__console_assert, "assert", flags); + duk__console_reg_vararg_func(ctx, duk__console_log, "log", flags); + duk__console_reg_vararg_func(ctx, duk__console_log, "debug", flags); /* alias to console.log */ + duk__console_reg_vararg_func(ctx, duk__console_trace, "trace", flags); + duk__console_reg_vararg_func(ctx, duk__console_info, "info", flags); + duk__console_reg_vararg_func(ctx, duk__console_warn, "warn", flags); + duk__console_reg_vararg_func(ctx, duk__console_error, "error", flags); + duk__console_reg_vararg_func(ctx, duk__console_error, "exception", flags); /* alias to console.error */ + duk__console_reg_vararg_func(ctx, duk__console_dir, "dir", flags); + + duk_put_global_string(ctx, "console"); + + /* Proxy wrapping: ensures any undefined console method calls are + * ignored silently. This is required specifically by the + * DeveloperToolsWG proposal (and is implemented also by Firefox: + * https://bugzilla.mozilla.org/show_bug.cgi?id=629607). + */ + + if (flags & DUK_CONSOLE_PROXY_WRAPPER) { + /* Tolerate errors: Proxy may be disabled. */ + duk_peval_string_noresult(ctx, + "(function(){" + "var D=function(){};" + "console=new Proxy(console,{" + "get:function(t,k){" + "var v=t[k];" + "return typeof v==='function'?v:D;" + "}" + "});" + "})();" + ); + } +} |