1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

fix(inspect): eliminate panic inspecting event classes (#10979)

This commit is contained in:
David Sherret 2021-06-24 09:43:41 -04:00 committed by Ryan Dahl
parent 8f699d6133
commit 1909da47fe
2 changed files with 79 additions and 15 deletions

View file

@ -1,5 +1,10 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals, unitTest } from "./test_util.ts";
import {
assert,
assertEquals,
assertStringIncludes,
unitTest,
} from "./test_util.ts";
unitTest(function eventInitializedWithType(): void {
const type = "click";
@ -127,3 +132,30 @@ unitTest(function eventInspectOutput(): void {
assertEquals(Deno.inspect(event), outputProvider(event));
}
});
unitTest(function inspectEvent(): void {
// has a customInspect implementation that previously would throw on a getter
assertEquals(
Deno.inspect(Event.prototype),
`Event {
bubbles: [Getter/Setter],
cancelable: [Getter/Setter],
composed: [Getter/Setter],
currentTarget: [Getter/Setter],
defaultPrevented: [Getter/Setter],
eventPhase: [Getter/Setter],
srcElement: [Getter/Setter],
target: [Getter/Setter],
returnValue: [Getter/Setter],
timeStamp: [Getter/Setter],
type: [Getter/Setter]
}`,
);
// ensure this still works
assertStringIncludes(
Deno.inspect(new Event("test")),
// check a substring because one property is a timestamp
`Event {\n bubbles: false,\n cancelable: false,`,
);
});

View file

@ -144,7 +144,7 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, EVENT_PROPS, inspect);
return inspect(buildFilteredPropertyInspectObject(this, EVENT_PROPS));
}
get type() {
@ -395,9 +395,41 @@
}
}
function buildCustomInspectOutput(object, keys, inspect) {
const inspectObject = Object.fromEntries(keys.map((k) => [k, object[k]]));
return `${object.constructor.name} ${inspect(inspectObject)}`;
function buildFilteredPropertyInspectObject(object, keys) {
// forward the subset of properties from `object` without evaluating
// as evaluation could lead to an error, which is better handled
// in the inspect code
return new Proxy({}, {
get(_target, key) {
if (key === Symbol.toStringTag) {
return object.constructor?.name;
} else if (keys.includes(key)) {
return Reflect.get(object, key);
} else {
return undefined;
}
},
getOwnPropertyDescriptor(_target, key) {
if (!keys.includes(key)) {
return undefined;
}
return Reflect.getOwnPropertyDescriptor(object, key) ??
(object.prototype &&
Reflect.getOwnPropertyDescriptor(object.prototype, key)) ??
{
configurable: true,
enumerable: true,
value: object[key],
};
},
has(_target, key) {
return keys.includes(key);
},
ownKeys() {
return keys;
},
});
}
function defineEnumerableProps(
@ -1053,14 +1085,14 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, [
return inspect(buildFilteredPropertyInspectObject(this, [
...EVENT_PROPS,
"message",
"filename",
"lineno",
"colno",
"error",
], inspect);
]));
}
}
@ -1107,12 +1139,12 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, [
return inspect(buildFilteredPropertyInspectObject(this, [
...EVENT_PROPS,
"wasClean",
"code",
"reason",
], inspect);
]));
}
}
@ -1134,12 +1166,12 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, [
return inspect(buildFilteredPropertyInspectObject(this, [
...EVENT_PROPS,
"data",
"origin",
"lastEventId",
], inspect);
]));
}
}
@ -1164,10 +1196,10 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, [
return inspect(buildFilteredPropertyInspectObject(this, [
...EVENT_PROPS,
"detail",
], inspect);
]));
}
}
@ -1187,12 +1219,12 @@
}
[Symbol.for("Deno.customInspect")](inspect) {
return buildCustomInspectOutput(this, [
return inspect(buildFilteredPropertyInspectObject(this, [
...EVENT_PROPS,
"lengthComputable",
"loaded",
"total",
], inspect);
]));
}
}