Skip to content

Commit

Permalink
- memo_method abstraction to implement methods as one-liners
Browse files Browse the repository at this point in the history
- add console().info(), console().warn(), console().clear()
  • Loading branch information
dherman committed Oct 2, 2024
1 parent 77f89cc commit ebfa9dc
Showing 1 changed file with 32 additions and 27 deletions.
59 changes: 32 additions & 27 deletions crates/neon/src/node/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ use crate::{
object::Object,
result::{JsResult, NeonResult},
thread::LocalKey,
types::{JsFunction, JsObject},
types::{extract::TryIntoJs, function::BindOptions, JsFunction, JsObject},
};

static CONSOLE: LocalKey<Root<JsObject>> = LocalKey::new();
static LOG: LocalKey<Root<JsFunction>> = LocalKey::new();
static ERROR: LocalKey<Root<JsFunction>> = LocalKey::new();
static INFO: LocalKey<Root<JsFunction>> = LocalKey::new();
static WARN: LocalKey<Root<JsFunction>> = LocalKey::new();
static CLEAR: LocalKey<Root<JsFunction>> = LocalKey::new();

pub struct Console<'a, 'cx: 'a, C: Context<'cx>> {
pub(crate) cx: &'a mut C,
Expand All @@ -37,6 +40,22 @@ impl<'a, 'cx: 'a, C: Context<'cx>> Console<'a, 'cx, C> {
Ok(v.to_inner(self.cx))
}

fn memo_method<F>(
&mut self,
cache: &'static LocalKey<Root<JsFunction>>,
get_container: F,
key: &str,
) -> NeonResult<BindOptions<'_, 'cx>>
where
F: FnOnce(&mut Self) -> JsResult<'cx, JsObject>,
{
let container = get_container(self)?;
let function = self.memo(cache, |_| Ok(container), key)?;
let mut method = function.bind(self.cx.cx_mut());
method.this(container)?;
Ok(method)
}

pub(crate) fn new(cx: &'a mut C) -> Self {
Self {
cx,
Expand All @@ -48,37 +67,23 @@ impl<'a, 'cx: 'a, C: Context<'cx>> Console<'a, 'cx, C> {
self.memo(&CONSOLE, |c| Ok(c.cx.global_object()), "console")
}

fn log_function(&mut self) -> JsResult<'cx, JsFunction> {
self.memo(&LOG, |c| c.console_object(), "log")
pub fn log<T: TryIntoJs<'cx>>(&mut self, msg: T) -> NeonResult<()> {
self.memo_method(&LOG, |c| c.console_object(), "log")?.arg(msg)?.exec()
}

fn error_function(&mut self) -> JsResult<'cx, JsFunction> {
let console = self.console_object()?;
let function = ERROR.get_or_try_init(self.cx, |cx| {
let log: Handle<JsFunction> = console.get(cx, "error")?;
Ok(log.root(cx))
})?;
Ok(function.to_inner(self.cx))
pub fn error<T: TryIntoJs<'cx>>(&mut self, msg: T) -> NeonResult<()> {
self.memo_method(&ERROR, |c| c.console_object(), "error")?.arg(msg)?.exec()
}

pub fn info<T: TryIntoJs<'cx>>(&mut self, msg: T) -> NeonResult<()> {
self.memo_method(&INFO, |c| c.console_object(), "info")?.arg(msg)?.exec()
}

// FIXME: when we land #1056, this can get simplified
// FIXME: msg should be a generic TryIntoJs
pub fn log(&mut self, msg: &str) -> NeonResult<()> {
let function = self.log_function()?;
let console = self.console_object()?;
let msg = self.cx.string(msg);
let args = vec![msg.upcast()];
function.call(self.cx, console, args)?;
Ok(())
pub fn warn<T: TryIntoJs<'cx>>(&mut self, msg: T) -> NeonResult<()> {
self.memo_method(&WARN, |c| c.console_object(), "warn")?.arg(msg)?.exec()
}

// FIXME: msg should be a generic TryIntoJs
pub fn error(&mut self, msg: &str) -> NeonResult<()> {
let function = self.error_function()?;
let console = self.console_object()?;
let msg = self.cx.string(msg);
let args = vec![msg.upcast()];
function.call(self.cx, console, args)?;
Ok(())
pub fn clear<T: TryIntoJs<'cx>>(&mut self) -> NeonResult<()> {
self.memo_method(&CLEAR, |c| c.console_object(), "clear")?.exec()
}
}

0 comments on commit ebfa9dc

Please sign in to comment.