diff options
-rw-r--r-- | cli/dts/lib.deno.ns.d.ts | 2 | ||||
-rw-r--r-- | cli/rt/02_console.js | 19 | ||||
-rw-r--r-- | cli/tests/unit/console_test.ts | 47 | ||||
-rw-r--r-- | core/bindings.rs | 61 |
4 files changed, 127 insertions, 2 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 15b390fd1..141e66a24 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -1952,6 +1952,8 @@ declare namespace Deno { compact?: boolean; /** The maximum number of iterable entries to print. Defaults to 100. */ iterableLimit?: number; + /** Show a Proxy's target and handler. Defaults to false. */ + showProxy?: boolean; } /** Converts the input into a string that has the same format as printed by diff --git a/cli/rt/02_console.js b/cli/rt/02_console.js index e3492772d..00ecd3aac 100644 --- a/cli/rt/02_console.js +++ b/cli/rt/02_console.js @@ -154,6 +154,7 @@ trailingComma: false, compact: true, iterableLimit: 100, + showProxy: false, }; const DEFAULT_INDENT = " "; // Default indent string @@ -400,6 +401,13 @@ level, inspectOptions, ) { + const proxyDetails = Deno.core.getProxyDetails(value); + if (proxyDetails != null) { + return inspectOptions.showProxy + ? inspectProxy(proxyDetails, ctx, level, inspectOptions) + : inspectValue(proxyDetails[0], ctx, level, inspectOptions); + } + switch (typeof value) { case "string": return value; @@ -657,7 +665,16 @@ return `Promise { ${str} }`; } - // TODO: Proxy + function inspectProxy( + targetAndHandler, + ctx, + level, + inspectOptions, + ) { + return `Proxy ${ + inspectArray(targetAndHandler, ctx, level, inspectOptions) + }`; + } function inspectRawObject( value, diff --git a/cli/tests/unit/console_test.ts b/cli/tests/unit/console_test.ts index 3d1ace6bd..384b5d2c8 100644 --- a/cli/tests/unit/console_test.ts +++ b/cli/tests/unit/console_test.ts @@ -1367,3 +1367,50 @@ unitTest(function inspectIterableLimit(): void { `Map { "a" => 1, "b" => 2, ... 1 more items }`, ); }); + +unitTest(function inspectProxy(): void { + assertEquals( + Deno.inspect( + new Proxy([1, 2, 3], { get(): void {} }), + ), + "[ 1, 2, 3 ]", + ); + assertEquals( + Deno.inspect( + new Proxy({ key: "value" }, { get(): void {} }), + ), + `{ key: "value" }`, + ); + assertEquals( + Deno.inspect(new Proxy([1, 2, 3], { get(): void {} }), { showProxy: true }), + "Proxy [ [ 1, 2, 3 ], { get: [Function: get] } ]", + ); + assertEquals( + Deno.inspect( + new Proxy({ a: 1 }, { + set(): boolean { + return false; + }, + }), + { showProxy: true }, + ), + "Proxy [ { a: 1 }, { set: [Function: set] } ]", + ); + assertEquals( + Deno.inspect( + new Proxy([1, 2, 3, 4, 5, 6, 7], { get(): void {} }), + { showProxy: true }, + ), + `Proxy [ [ + 1, 2, 3, 4, + 5, 6, 7 + ], { get: [Function: get] } ]`, + ); + assertEquals( + Deno.inspect( + new Proxy(function fn() {}, { get(): void {} }), + { showProxy: true }, + ), + "Proxy [ [Function: fn], { get: [Function: get] } ]", + ); +}); diff --git a/core/bindings.rs b/core/bindings.rs index 55cb080f6..0a755c298 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -50,7 +50,10 @@ lazy_static! { }, v8::ExternalReference { function: get_promise_details.map_fn_to() - } + }, + v8::ExternalReference { + function: get_proxy_details.map_fn_to() + }, ]); } @@ -181,6 +184,18 @@ pub fn initialize_context<'s>( get_promise_details_val.into(), ); + let get_proxy_details_key = + v8::String::new(scope, "getProxyDetails").unwrap(); + let get_proxy_details_tmpl = + v8::FunctionTemplate::new(scope, get_proxy_details); + let get_proxy_details_val = + get_proxy_details_tmpl.get_function(scope).unwrap(); + core_val.set( + scope, + get_proxy_details_key.into(), + get_proxy_details_val.into(), + ); + let shared_key = v8::String::new(scope, "shared").unwrap(); core_val.set_accessor(scope, shared_key.into(), shared_getter); @@ -797,6 +812,50 @@ fn get_promise_details( } } +// Based on https://github.com/nodejs/node/blob/1e470510ff74391d7d4ec382909ea8960d2d2fbc/src/node_util.cc +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +fn get_proxy_details( + scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + // Return undefined if it's not a proxy. + let proxy = match v8::Local::<v8::Proxy>::try_from(args.get(0)) { + Ok(val) => val, + Err(_) => { + return; + } + }; + + let proxy_details = v8::Array::new(scope, 2); + let js_zero = v8::Integer::new(scope, 0); + let js_one = v8::Integer::new(scope, 1); + let target = proxy.get_target(scope); + let handler = proxy.get_handler(scope); + proxy_details.set(scope, js_zero.into(), target); + proxy_details.set(scope, js_one.into(), handler); + rv.set(proxy_details.into()); +} + fn throw_type_error<'s>( scope: &mut v8::HandleScope<'s>, message: impl AsRef<str>, |