fix: ConsoleObject handles proxy better (#9042)

* fix: ConsoleObject handles proxy better

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
dave caruso
2024-02-21 18:33:54 -08:00
committed by GitHub
parent 048ae7c7b8
commit 44f7ddd2ff
6 changed files with 97 additions and 44 deletions

View File

@@ -915,7 +915,6 @@ pub const Formatter = struct {
JSON,
toJSON,
NativeCode,
ArrayBuffer,
JSX,
Event,
@@ -923,6 +922,9 @@ pub const Formatter = struct {
GetterSetter,
CustomGetterSetter,
Proxy,
RevokedProxy,
pub fn isPrimitive(this: Tag) bool {
return switch (this) {
.String,
@@ -971,15 +973,20 @@ pub const Formatter = struct {
JSON: void,
toJSON: void,
NativeCode: void,
ArrayBuffer: void,
JSX: void,
Event: void,
GetterSetter: void,
CustomGetterSetter: void,
Proxy: void,
RevokedProxy: void,
pub fn isPrimitive(this: @This()) bool {
return @as(Tag, this).isPrimitive();
}
pub fn tag(this: @This()) Tag {
return @as(Tag, this);
}
},
cell: JSValue.JSType = JSValue.JSType.Cell,
};
@@ -1126,10 +1133,17 @@ pub const Formatter = struct {
.Object,
.FinalObject,
.ProxyObject,
.ModuleNamespaceObject,
=> .Object,
.ProxyObject => tag: {
const handler = value.getProxyInternalField(.handler);
if (handler == .zero or handler == .undefined or handler == .null) {
break :tag .RevokedProxy;
}
break :tag .Proxy;
},
.GlobalObject => if (!opts.hide_global)
.Object
else
@@ -2877,7 +2891,20 @@ pub const Formatter = struct {
writer.writeAll(" ]");
},
else => {},
.RevokedProxy => {
this.addForNewLine("<Revoked Proxy>".len);
writer.print(comptime Output.prettyFmt("<r><cyan>\\<Revoked Proxy\\><r>", enable_ansi_colors), .{});
},
.Proxy => {
const target = value.getProxyInternalField(.target);
if (Environment.allow_assert) {
// Proxy does not allow non-objects here.
std.debug.assert(target.isCell());
}
// TODO: if (options.showProxy), print like `Proxy { target: ..., handlers: ... }`
// this is default off so it is not used.
this.format(ConsoleObject.Formatter.Tag.get(target, this.globalThis), Writer, writer_, target, this.globalThis, enable_ansi_colors);
},
}
}
@@ -2908,9 +2935,6 @@ pub const Formatter = struct {
}
pub fn format(this: *ConsoleObject.Formatter, result: Tag.Result, comptime Writer: type, writer: Writer, value: JSValue, globalThis: *JSGlobalObject, comptime enable_ansi_colors: bool) void {
if (comptime is_bindgen) {
return;
}
const prevGlobalThis = this.globalThis;
defer this.globalThis = prevGlobalThis;
this.globalThis = globalThis;
@@ -2919,44 +2943,11 @@ pub const Formatter = struct {
// comptime var so we have to repeat it here. The rationale there is
// it _should_ limit the stack usage because each version of the
// function will be relatively small
switch (result.tag) {
.StringPossiblyFormatted => this.printAs(.StringPossiblyFormatted, Writer, writer, value, result.cell, enable_ansi_colors),
.String => this.printAs(.String, Writer, writer, value, result.cell, enable_ansi_colors),
.Undefined => this.printAs(.Undefined, Writer, writer, value, result.cell, enable_ansi_colors),
.Double => this.printAs(.Double, Writer, writer, value, result.cell, enable_ansi_colors),
.Integer => this.printAs(.Integer, Writer, writer, value, result.cell, enable_ansi_colors),
.Null => this.printAs(.Null, Writer, writer, value, result.cell, enable_ansi_colors),
.Boolean => this.printAs(.Boolean, Writer, writer, value, result.cell, enable_ansi_colors),
.Array => this.printAs(.Array, Writer, writer, value, result.cell, enable_ansi_colors),
.Object => this.printAs(.Object, Writer, writer, value, result.cell, enable_ansi_colors),
.Function => this.printAs(.Function, Writer, writer, value, result.cell, enable_ansi_colors),
.Class => this.printAs(.Class, Writer, writer, value, result.cell, enable_ansi_colors),
.Error => this.printAs(.Error, Writer, writer, value, result.cell, enable_ansi_colors),
.ArrayBuffer, .TypedArray => this.printAs(.TypedArray, Writer, writer, value, result.cell, enable_ansi_colors),
.Map => this.printAs(.Map, Writer, writer, value, result.cell, enable_ansi_colors),
.MapIterator => this.printAs(.MapIterator, Writer, writer, value, result.cell, enable_ansi_colors),
.SetIterator => this.printAs(.SetIterator, Writer, writer, value, result.cell, enable_ansi_colors),
.Set => this.printAs(.Set, Writer, writer, value, result.cell, enable_ansi_colors),
.Symbol => this.printAs(.Symbol, Writer, writer, value, result.cell, enable_ansi_colors),
.BigInt => this.printAs(.BigInt, Writer, writer, value, result.cell, enable_ansi_colors),
.GlobalObject => this.printAs(.GlobalObject, Writer, writer, value, result.cell, enable_ansi_colors),
.Private => this.printAs(.Private, Writer, writer, value, result.cell, enable_ansi_colors),
.Promise => this.printAs(.Promise, Writer, writer, value, result.cell, enable_ansi_colors),
switch (result.tag.tag()) {
inline else => |tag| this.printAs(tag, Writer, writer, value, result.cell, enable_ansi_colors),
// Call JSON.stringify on the value
.JSON => this.printAs(.JSON, Writer, writer, value, result.cell, enable_ansi_colors),
// Call value.toJSON() and print as an object
.toJSON => this.printAs(.toJSON, Writer, writer, value, result.cell, enable_ansi_colors),
.NativeCode => this.printAs(.NativeCode, Writer, writer, value, result.cell, enable_ansi_colors),
.JSX => this.printAs(.JSX, Writer, writer, value, result.cell, enable_ansi_colors),
.Event => this.printAs(.Event, Writer, writer, value, result.cell, enable_ansi_colors),
.GetterSetter => this.printAs(.GetterSetter, Writer, writer, value, result.cell, enable_ansi_colors),
.CustomGetterSetter => this.printAs(.CustomGetterSetter, Writer, writer, value, result.cell, enable_ansi_colors),
.CustomFormattedObject => |callback| {
this.custom_formatted_object = callback;
.CustomFormattedObject => {
this.custom_formatted_object = result.tag.CustomFormattedObject;
this.printAs(.CustomFormattedObject, Writer, writer, value, result.cell, enable_ansi_colors);
},
}

View File

@@ -32,6 +32,7 @@
#include "JavaScriptCore/JSObject.h"
#include "JavaScriptCore/JSSet.h"
#include "JavaScriptCore/JSString.h"
#include "JavaScriptCore/ProxyObject.h"
#include "JavaScriptCore/Microtask.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "JavaScriptCore/ParserError.h"
@@ -5433,3 +5434,8 @@ CPP_DECL bool JSC__CustomGetterSetter__isSetterNull(JSC__CustomGetterSetter* get
{
return gettersetter->setter() == nullptr;
}
CPP_DECL JSC__JSValue Bun__ProxyObject__getInternalField(JSC__JSValue value, uint32_t id)
{
return JSValue::encode(jsCast<ProxyObject*>(JSValue::decode(value))->internalField((ProxyObject::Field)id).get());
}

View File

@@ -5310,6 +5310,18 @@ pub const JSValue = enum(JSValueReprInt) {
else
null;
}
extern fn Bun__ProxyObject__getInternalField(this: JSValue, field: ProxyInternalField) JSValue;
const ProxyInternalField = enum(u32) {
target = 0,
handler = 1,
};
/// Asserts `this` is a proxy
pub fn getProxyInternalField(this: JSValue, field: ProxyInternalField) JSValue {
return Bun__ProxyObject__getInternalField(this, field);
}
};
extern "c" fn AsyncContextFrame__withAsyncContextIfNeeded(global: *JSGlobalObject, callback: JSValue) JSValue;

View File

@@ -353,6 +353,14 @@ export function windowsEnv(internalEnv: InternalEnvMap, envMapList: Array<string
//
// it throws "Cannot convert a Symbol value to a string"
(internalEnv as any)[Bun.inspect.custom] = () => {
let o = {};
for (let k of envMapList) {
o[k] = internalEnv[k.toUpperCase()];
}
return o;
};
return new Proxy(internalEnv, {
get(_, p) {
return typeof p === "string" ? Reflect.get(internalEnv, p.toUpperCase()) : undefined;

View File

@@ -244,3 +244,8 @@ myCustomName {
{
"": "",
}
{
hello: 2,
}
<Revoked Proxy>
custom inspect

View File

@@ -173,3 +173,34 @@ console.log(hole([1, 2, 3], 0));
// It appears to not be set and I don't know why.
console.log({ "": "" });
{
// proxy
const proxy = Proxy.revocable(
{ hello: 2 },
{
get(target, prop, receiver) {
console.log("FAILED: GET", prop);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log("FAILED: SET", prop, value);
return Reflect.set(target, prop, value, receiver);
},
},
);
console.log(proxy.proxy);
proxy.revoke();
console.log(proxy.proxy);
}
{
// proxy custom inspect
const proxy = new Proxy(
{
[Bun.inspect.custom]: () => "custom inspect",
},
{},
);
console.log(proxy);
}