diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index f944b21b8d25fd..b4626374d81648 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -34,15 +34,16 @@ delete Object.prototype.__proto__; } } + function printStderr(msg) { + core.print(msg, true); + } + function debug(...args) { if (logDebug) { const stringifiedArgs = args.map((arg) => typeof arg === "string" ? arg : JSON.stringify(arg) ).join(" "); - // adding a non-zero integer value to the end of the debug string causes - // the message to be printed to stderr instead of stdout, which is better - // aligned to the behaviour of debug messages - core.print(`DEBUG ${logSource} - ${stringifiedArgs}\n`, 1); + printStderr(`DEBUG ${logSource} - ${stringifiedArgs}\n`); } } @@ -52,7 +53,7 @@ delete Object.prototype.__proto__; ? String(arg) : JSON.stringify(arg) ).join(" "); - core.print(`ERROR ${logSource} = ${stringifiedArgs}\n`, 1); + printStderr(`ERROR ${logSource} = ${stringifiedArgs}\n`); } class AssertionError extends Error { diff --git a/cli/tsc/compiler.d.ts b/cli/tsc/compiler.d.ts index 13e6564b44dbb4..e5ce12cd323f5d 100644 --- a/cli/tsc/compiler.d.ts +++ b/cli/tsc/compiler.d.ts @@ -36,7 +36,7 @@ declare global { // deno-lint-ignore no-explicit-any opSync<T>(name: string, params: T): any; ops(): void; - print(msg: string, code?: number): void; + print(msg: string, stderr: bool): void; registerErrorClass( name: string, Ctor: typeof Error, diff --git a/core/bindings.rs b/core/bindings.rs index ea45daff4c44fb..8a32bc5da462fc 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -13,7 +13,6 @@ use serde::Serialize; use serde_v8::to_v8; use std::convert::TryFrom; use std::convert::TryInto; -use std::io::{stdout, Write}; use std::option::Option; use url::Url; use v8::MapFnTo; @@ -21,9 +20,6 @@ use v8::MapFnTo; lazy_static::lazy_static! { pub static ref EXTERNAL_REFERENCES: v8::ExternalReferences = v8::ExternalReferences::new(&[ - v8::ExternalReference { - function: print.map_fn_to() - }, v8::ExternalReference { function: opcall.map_fn_to() }, @@ -117,7 +113,6 @@ pub fn initialize_context<'s>( deno_val.set(scope, core_key.into(), core_val.into()); // Bind functions to Deno.core.* - set_func(scope, core_val, "print", print); set_func(scope, core_val, "opcall", opcall); set_func( scope, @@ -268,41 +263,6 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { }; } -fn print( - scope: &mut v8::HandleScope, - args: v8::FunctionCallbackArguments, - _rv: v8::ReturnValue, -) { - let arg_len = args.length(); - if !(0..=2).contains(&arg_len) { - return throw_type_error(scope, "Expected a maximum of 2 arguments."); - } - - let obj = args.get(0); - let is_err_arg = args.get(1); - - let mut is_err = false; - if arg_len == 2 { - let int_val = match is_err_arg.integer_value(scope) { - Some(v) => v, - None => return throw_type_error(scope, "Invalid argument. Argument 2 should indicate whether or not to print to stderr."), - }; - is_err = int_val != 0; - }; - let tc_scope = &mut v8::TryCatch::new(scope); - let str_ = match obj.to_string(tc_scope) { - Some(s) => s, - None => v8::String::new(tc_scope, "").unwrap(), - }; - if is_err { - eprint!("{}", str_.to_rust_string_lossy(tc_scope)); - stdout().flush().unwrap(); - } else { - print!("{}", str_.to_rust_string_lossy(tc_scope)); - stdout().flush().unwrap(); - } -} - fn opcall<'s>( scope: &mut v8::HandleScope<'s>, args: v8::FunctionCallbackArguments, diff --git a/core/core.js b/core/core.js index e5998fbc84eeb5..729ca4faa40a1e 100644 --- a/core/core.js +++ b/core/core.js @@ -124,6 +124,10 @@ opSync("op_close", rid); } + function print(str, isErr = false) { + opSync("op_print", [str, isErr]); + } + // Provide bootstrap namespace window.__bootstrap = {}; // Extra Deno.core.* exports @@ -132,6 +136,7 @@ opSync, ops, close, + print, resources, registerErrorClass, handleAsyncMsgFromRust, diff --git a/core/lib.rs b/core/lib.rs index adfd9a6a22c437..4e7345c4028625 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -65,6 +65,7 @@ pub use crate::ops::OpState; pub use crate::ops::OpTable; pub use crate::ops::PromiseId; pub use crate::ops_builtin::op_close; +pub use crate::ops_builtin::op_print; pub use crate::ops_builtin::op_resources; pub use crate::ops_json::op_async; pub use crate::ops_json::op_sync; diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs index 96aca5c53350da..546d9cf32d1ac3 100644 --- a/core/ops_builtin.rs +++ b/core/ops_builtin.rs @@ -7,6 +7,7 @@ use crate::resources::ResourceId; use crate::Extension; use crate::OpState; use crate::ZeroCopyBuf; +use std::io::{stdout, Write}; pub(crate) fn init_builtins() -> Extension { Extension::builder() @@ -17,6 +18,7 @@ pub(crate) fn init_builtins() -> Extension { )) .ops(vec![ ("op_close", op_sync(op_close)), + ("op_print", op_sync(op_print)), ("op_resources", op_sync(op_resources)), ]) .build() @@ -52,3 +54,20 @@ pub fn op_close( Ok(()) } + +/// Builtin utility to print to stdout/stderr +pub fn op_print( + _state: &mut OpState, + args: (String, bool), + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<(), AnyError> { + let (msg, is_err) = args; + if is_err { + eprint!("{}", msg); + stdout().flush().unwrap(); + } else { + print!("{}", msg); + stdout().flush().unwrap(); + } + Ok(()) +}