netsurf/content/handlers/javascript/duktape/Console.bnd
Daniel Silverstone a325d6b474 Console.bnd: Support attempts to log when Window has gone
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
2019-08-01 09:22:09 +01:00

200 lines
4.1 KiB
Plaintext

/* Console binding for browser using duktape and libdom
*
* Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
* Copyright 2015 Daniel Silverstone <dsilvers@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* Released under the terms of the MIT License,
* http://www.opensource.org/licenses/mit-license
*/
class Console {
private unsigned int group;
prologue %{
#include <nsutils/time.h>
#include "netsurf/browser_window.h"
#define CONSOLE_TIMERS MAGIC(ConsoleTimers)
static void
write_log_entry(duk_context *ctx, unsigned int group, browser_window_console_flags flags)
{
/* objs... */
dukky_push_generics(ctx, "consoleFormatter");
duk_insert(ctx, 0);
if (dukky_pcall(ctx, duk_get_top(ctx) - 1, false)) {
/* Failed to convert somehow, oh dear, you get to keep
* all the pieces.
*/
duk_pop(ctx);
duk_push_string(ctx, "Oh dear, formatter went banananas");
}
/* str?objs?... */
for (int i = 0; i < duk_get_top(ctx); ++i) {
(void)duk_safe_to_string(ctx, i);
}
/* strs... */
for (unsigned int u = 0; u < group; ++u) {
duk_push_lstring(ctx, " ", 1);
duk_insert(ctx, 0);
}
/* spcs... strs... */
duk_concat(ctx, duk_get_top(ctx));
/* str */
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, PRIVATE_MAGIC);
window_private_t *priv_win = duk_get_pointer(ctx, -1);
duk_pop(ctx);
duk_size_t msglen;
const char *msg = duk_safe_to_lstring(ctx, 0, &msglen);
if (priv_win == NULL ||
browser_window_console_log(priv_win->win, BW_CS_SCRIPT_CONSOLE,
msg, msglen,
flags) != NSERROR_OK) {
NSLOG(netsurf, DEBUG, "Unable to log: %s", duk_safe_to_string(ctx, 0));
}
}
%};
};
init Console ()
%{
priv->group = 0;
duk_push_object(ctx);
duk_put_prop_string(ctx, 0, CONSOLE_TIMERS);
%}
method Console::group ()
%{
priv->group ++;
return 0;
%}
method Console::groupCollapsed ()
%{
priv->group ++;
return 0;
%}
method Console::groupEnd ()
%{
if (priv->group)
priv->group --;
return 0;
%}
method Console::info()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
method Console::debug()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_DEBUG);
return 0;
%}
method Console::error()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_ERROR);
return 0;
%}
method Console::log()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_LOG);
return 0;
%}
method Console::warn()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_WARN);
return 0;
%}
method Console::dir()
%{
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
method Console::time()
%{
uint64_t time_ms = 0;
if (nsu_getmonotonic_ms(&time_ms) != NSUERROR_OK)
return 0;
if (!duk_is_string(ctx, 0)) {
return duk_error(ctx, DUK_ERR_ERROR, "Console.time() takes a string");
}
duk_set_top(ctx, 1);
duk_push_uint(ctx, (duk_uint_t)time_ms);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, CONSOLE_TIMERS);
duk_insert(ctx, 0);
duk_pop(ctx);
duk_put_prop(ctx, 0);
return 0;
%}
method Console::timeEnd()
%{
uint64_t time_ms = 0;
uint64_t old_time_ms = 0;
if (nsu_getmonotonic_ms(&time_ms) != NSUERROR_OK)
return 0;
if (!duk_is_string(ctx, 0)) {
return duk_error(ctx, DUK_ERR_ERROR, "Console.time() takes a string");
}
duk_set_top(ctx, 1);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, CONSOLE_TIMERS);
duk_insert(ctx, 0);
duk_pop(ctx);
duk_dup(ctx, -1);
duk_get_prop(ctx, 0);
if (duk_is_undefined(ctx, -1)) {
duk_pop(ctx);
duk_push_uint(ctx, (duk_uint_t)time_ms);
}
/* timers timername oldval */
old_time_ms = duk_to_uint32(ctx, -1);
duk_pop(ctx);
duk_dup(ctx, -1);
duk_insert(ctx, 0);
duk_del_prop(ctx, 0);
duk_push_string(ctx, "Timer elapsed: ");
duk_insert(ctx, 0);
duk_push_sprintf(ctx, "%lu ms", (duk_uint_t)(time_ms - old_time_ms));
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
method Console::trace ()
%{
duk_idx_t i = duk_push_error_object(ctx, DUK_ERR_ERROR, "Dummy Error");
duk_get_prop_string(ctx, i, "stack");
duk_safe_to_string(ctx, -1);
duk_insert(ctx, 0);
duk_set_top(ctx, 1);
write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}