summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/dts/lib.deno.ns.d.ts2
-rw-r--r--cli/tests/041_dyn_import_eval.out2
-rw-r--r--cli/tests/042_dyn_import_evalcontext.ts.out2
-rw-r--r--cli/tests/070_location.ts.out2
-rw-r--r--cli/tests/071_location_unset.ts.out2
-rw-r--r--cli/tests/fix_js_imports.ts.out2
-rw-r--r--cli/tests/top_level_await_loop.out4
-rw-r--r--cli/tests/unit/console_test.ts47
-rw-r--r--runtime/js/02_console.js54
9 files changed, 104 insertions, 13 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts
index b607554e1..04bf8ad80 100644
--- a/cli/dts/lib.deno.ns.d.ts
+++ b/cli/dts/lib.deno.ns.d.ts
@@ -2034,6 +2034,8 @@ declare namespace Deno {
trailingComma?: boolean;
/*** Evaluate the result of calling getters. Defaults to false. */
getters?: boolean;
+ /** Show an object's non-enumerable properties. Defaults to false. */
+ showHidden?: boolean;
}
/** Converts the input into a string that has the same format as printed by
diff --git a/cli/tests/041_dyn_import_eval.out b/cli/tests/041_dyn_import_eval.out
index a4c44eff8..12a45b8da 100644
--- a/cli/tests/041_dyn_import_eval.out
+++ b/cli/tests/041_dyn_import_eval.out
@@ -1 +1 @@
-Module { isMod4: true, [Symbol(Symbol.toStringTag)]: "Module" }
+Module { isMod4: true }
diff --git a/cli/tests/042_dyn_import_evalcontext.ts.out b/cli/tests/042_dyn_import_evalcontext.ts.out
index a4c44eff8..12a45b8da 100644
--- a/cli/tests/042_dyn_import_evalcontext.ts.out
+++ b/cli/tests/042_dyn_import_evalcontext.ts.out
@@ -1 +1 @@
-Module { isMod4: true, [Symbol(Symbol.toStringTag)]: "Module" }
+Module { isMod4: true }
diff --git a/cli/tests/070_location.ts.out b/cli/tests/070_location.ts.out
index 3c08d53fc..e05561e58 100644
--- a/cli/tests/070_location.ts.out
+++ b/cli/tests/070_location.ts.out
@@ -1,5 +1,5 @@
[WILDCARD][Function: Location]
-Location { [Symbol(Symbol.toStringTag)]: "Location" }
+Location {}
Location {
hash: "#bat",
host: "foo",
diff --git a/cli/tests/071_location_unset.ts.out b/cli/tests/071_location_unset.ts.out
index 2c030a773..43308f3bd 100644
--- a/cli/tests/071_location_unset.ts.out
+++ b/cli/tests/071_location_unset.ts.out
@@ -1,4 +1,4 @@
[WILDCARD][Function: Location]
-Location { [Symbol(Symbol.toStringTag)]: "Location" }
+Location {}
error: Uncaught ReferenceError: Access to "location", run again with --location <href>.
[WILDCARD]
diff --git a/cli/tests/fix_js_imports.ts.out b/cli/tests/fix_js_imports.ts.out
index 4fb3b8f12..5e45122de 100644
--- a/cli/tests/fix_js_imports.ts.out
+++ b/cli/tests/fix_js_imports.ts.out
@@ -1 +1 @@
-Module { [Symbol(Symbol.toStringTag)]: "Module" }
+Module {}
diff --git a/cli/tests/top_level_await_loop.out b/cli/tests/top_level_await_loop.out
index d704e3afd..70e621e45 100644
--- a/cli/tests/top_level_await_loop.out
+++ b/cli/tests/top_level_await_loop.out
@@ -1,5 +1,5 @@
loading [WILDCARD]a.js
-loaded Module { default: [Function: Foo], [Symbol(Symbol.toStringTag)]: "Module" }
+loaded Module { default: [Function: Foo] }
loading [WILDCARD]b.js
-loaded Module { default: [Function: Bar], [Symbol(Symbol.toStringTag)]: "Module" }
+loaded Module { default: [Function: Bar] }
all loaded
diff --git a/cli/tests/unit/console_test.ts b/cli/tests/unit/console_test.ts
index fc23b1d70..286b693ff 100644
--- a/cli/tests/unit/console_test.ts
+++ b/cli/tests/unit/console_test.ts
@@ -310,7 +310,7 @@ unitTest(function consoleTestStringifyCircular(): void {
assertEquals(stringify(nestedObj), nestedObjExpected);
assertEquals(
stringify(JSON),
- 'JSON { [Symbol(Symbol.toStringTag)]: "JSON" }',
+ "JSON {}",
);
assertEquals(
stringify(console),
@@ -335,7 +335,6 @@ unitTest(function consoleTestStringifyCircular(): void {
clear: [Function: clear],
trace: [Function: trace],
indentLevel: 0,
- [Symbol(Symbol.toStringTag)]: "console",
[Symbol(isConsoleInstance)]: true
}`,
);
@@ -362,6 +361,50 @@ unitTest(function consoleTestStringifyFunctionWithPrototypeRemoved(): void {
assertEquals(stringify(agf), "[Function: agf]");
});
+unitTest(function consoleTestStringifyFunctionWithProperties(): void {
+ const f = () => "test";
+ f.x = () => "foo";
+ f.y = 3;
+ f.z = () => "baz";
+ f.b = function bar() {};
+ f.a = new Map();
+ assertEquals(
+ stringify({ f }),
+ `{
+ f: [Function: f] { x: [Function], y: 3, z: [Function], b: [Function: bar], a: Map {} }
+}`,
+ );
+
+ const t = () => {};
+ t.x = f;
+ f.s = f;
+ f.t = t;
+ assertEquals(
+ stringify({ f }),
+ `{
+ f: [Function: f] {
+ x: [Function],
+ y: 3,
+ z: [Function],
+ b: [Function: bar],
+ a: Map {},
+ s: [Circular],
+ t: [Function: t] { x: [Circular] }
+ }
+}`,
+ );
+
+ assertEquals(
+ stringify(Array),
+ `[Function: Array]`,
+ );
+
+ assertEquals(
+ stripColor(Deno.inspect(Array, { showHidden: true })),
+ `[Function: Array] { [Symbol(Symbol.species)]: [Getter] }`,
+ );
+});
+
unitTest(function consoleTestStringifyWithDepth(): void {
// deno-lint-ignore no-explicit-any
const nestedObj: any = { a: { b: { c: { d: { e: { f: 42 } } } } } };
diff --git a/runtime/js/02_console.js b/runtime/js/02_console.js
index bd6565e0e..5d174ece4 100644
--- a/runtime/js/02_console.js
+++ b/runtime/js/02_console.js
@@ -17,6 +17,17 @@
return Object.prototype.hasOwnProperty.call(obj, v);
}
+ function propertyIsEnumerable(obj, prop) {
+ if (
+ obj == null ||
+ typeof obj.propertyIsEnumerable !== "function"
+ ) {
+ return false;
+ }
+
+ return obj.propertyIsEnumerable(prop);
+ }
+
// Copyright Joyent, Inc. and other Node contributors. MIT license.
// Forked from Node's lib/internal/cli_table.js
@@ -159,6 +170,7 @@
showProxy: false,
colors: false,
getters: false,
+ showHidden: false,
};
const DEFAULT_INDENT = " "; // Default indent string
@@ -189,7 +201,8 @@
return inspectOptions.colors ? fn : (s) => s;
}
- function inspectFunction(value, _ctx) {
+ function inspectFunction(value, ctx, level, inspectOptions) {
+ const cyan = maybeColor(colors.cyan, inspectOptions);
if (customInspect in value && typeof value[customInspect] === "function") {
return String(value[customInspect]());
}
@@ -200,11 +213,32 @@
// use generic 'Function' instead.
cstrName = "Function";
}
+
+ // Our function may have properties, so we want to format those
+ // as if our function was an object
+ // If we didn't find any properties, we will just append an
+ // empty suffix.
+ let suffix = ``;
+ if (
+ Object.keys(value).length > 0 ||
+ Object.getOwnPropertySymbols(value).length > 0
+ ) {
+ const propString = inspectRawObject(value, ctx, level, inspectOptions);
+ // Filter out the empty string for the case we only have
+ // non-enumerable symbols.
+ if (
+ propString.length > 0 &&
+ propString !== "{}"
+ ) {
+ suffix = ` ${propString}`;
+ }
+ }
+
if (value.name && value.name !== "anonymous") {
// from MDN spec
- return `[${cstrName}: ${value.name}]`;
+ return cyan(`[${cstrName}: ${value.name}]`) + suffix;
}
- return `[${cstrName}]`;
+ return cyan(`[${cstrName}]`) + suffix;
}
function inspectIterable(
@@ -429,7 +463,12 @@
case "bigint": // Bigints are yellow
return yellow(`${value}n`);
case "function": // Function string is cyan
- return cyan(inspectFunction(value, ctx));
+ if (ctx.has(value)) {
+ // Circular string is cyan
+ return cyan("[Circular]");
+ }
+
+ return inspectFunction(value, ctx, level, inspectOptions);
case "object": // null is bold
if (value === null) {
return bold("null");
@@ -797,6 +836,13 @@
}
for (const key of symbolKeys) {
+ if (
+ !inspectOptions.showHidden &&
+ !propertyIsEnumerable(value, key)
+ ) {
+ continue;
+ }
+
if (inspectOptions.getters) {
let propertyValue;
let error;